【每日一题】5月18日「土」秘法地震
「土」秘法地震
https://ac.nowcoder.com/acm/problem/53676
解题方法
给定地图,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; }
每日一题 文章被收录于专栏
每日一题