![](https://img-blog.csdnimg.cn/6dafe4a0a8024460abb20be32a69b0c0.png)
![](https://img-blog.csdnimg.cn/59f34c638c4e4f8898587d4da553cdf2.png)
![](https://img-blog.csdnimg.cn/e3d16e12ae33407c97a011e8d212486c.png)
本题的突破口在于已知B的左下角为1,A中1的数量是有限的,所以我们可以枚举一下,把B的左下角依次放到A的每一个1的位置上,A最多有1000个1,最多会放1000次,枚举完之后我们再判断一下,如果放到某个A的位置上之后,能否匹配。如何判断A的局部与B匹配呢?
分别枚举A中的1000个数,判断一下在B中对应的位置是不是1,如果A中的数在B中的位置对应的是1的话就跳过,如果在B中这个位置是0的话,那表示不匹配,我们把每一个数都判断一遍,同时记录一下匹配了多少个数,这样判断完之后可以发现,A中是1的地方B中也是1,反过来还要判断一下,B中是1的地方A中是不是1呢?由于我们刚刚统计了A中在B区域内有多少个1了(比如有cnt个),只需要比较一下B中1的总数是不是cnt就可以了,如果B中1的总数也是cnt的话,那么就表示A和B完全匹配了。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1010, M = 55, INF = 1e8;
typedef pair<int, int> PII;
int n, l, s;
PII tree[N];
int b[M][M];
int main()
{
scanf("%d%d%d", &n, &l, &s);
for (int i = 0; i < n; ++ i)
scanf("%d%d", &tree[i].first, &tree[i].second);
int tc = 0;
for (int i = s; i >= 0; -- i)
{
for (int j = 0; j <= s; ++ j)
{
scanf("%d", &b[i][j]);
if (b[i][j] == 1) tc ++;
}
}
int res = 0;
for (int i = 0; i < n; ++ i)
{
int sx = tree[i].first, sy = tree[i].second;
// 判断是否越界(A的区域的边界)
if (sx + s > l || sy + s > l) continue;
int cnt = 0;
for (int j = 0; j < n; ++ j)
{
int dx = tree[j].first, dy = tree[j].second;
// 判断是否在B的区域内
if (dx >= sx && dx - sx <= s && dy >= sy && dy - sy <= s)
{
if (!b[dx - sx][dy - sy]) cnt = -INF;
else cnt ++;
}
}
if (cnt == tc) res ++;
}
printf("%d\n", res);
return 0;
}