解题方法
给定地图,0代表没有地雷,1代表有地雷,我们每次选取的范围,问选定范围有地雷的区域数量。
1、首先我们尝试纯暴力,直接枚举全部的左上角点,这里要,再去枚举区间是否有地雷
,如果取到最大的数据所要的时间
这时间复杂度太爆炸了。
2、我们想想办法改进下,我们发现,每更换一个左上角的点,我们都要对区间全部的点重新计算,这里太花时间了。有没有办法让我们在的时间里面知道这里面有没有地雷呢?是有的,那就是二维前缀和。
根据下面的图,我们知道,前区间有没有地雷只要
即前缀和数组,
是地图数组,
为0没有地雷,为1既有地雷。
这样预处理之后,我们就可以通过下面式子查询为左上角,
的矩阵中如果下面式子不为0即有地雷。
这样下来时间复杂度就变成了即地图大小。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int s = 0, w = 1; char ch = getchar();
while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
const int N = 1005;
int n, m, k;
char c;
char mp[N][N];
int num[N][N];
bool check(int i, int j) {
return num[i + k - 1][j + k - 1] - num[i - 1][j + k - 1] - num[i + k - 1][j - 1] + num[i - 1][j - 1];
}
int main() {
n = read(); m = read(); k = read();
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
c = getchar() - '0';
mp[i][j] = c;
}
getchar();
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
num[i][j] = num[i - 1][j] + num[i][j - 1] - num[i - 1][j - 1] + mp[i][j];
ll ans = 0;
for (int i = 1; i + k - 1 <= n; ++i)
for (int j = 1; j + k - 1 <= m; ++j)
if (check(i, j)) ++ans;
printf("%lld\n", ans);
return 0;
}

京公网安备 11010502036488号