【每日一题】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;
}
每日一题 文章被收录于专栏

每日一题

全部评论

相关推荐

双非坐过牢:非佬,可以啊10.28笔试,11.06评估11.11,11.12两面,11.19oc➕offer
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务