感受
今天空闲下来,于是做了这道题,乍一看,这不就是拿着一个正方形在地图上跑来跑去吗?
一眼题,巨水


思路
很容易得出,如果一个正方形内有1,那么对答案贡献+1
枚举所有正方形的位置只需要O(n * m),于是考虑如何快速check正方形内有无1。
这不是很眼熟吗?二维区间前缀和,于是就快速秒到这道题目了。
怎么求二维前缀和呢?太简单了,网上博客看一眼就懂了,这里就不赘述了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 10;
int n, m, k;
char s[maxn][maxn];
int dp[maxn][maxn];///dp[i][j]表示(1, 1) --- (i, j)构成的矩形区域中1的个数
void solve(){
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + (s[i][j] == '1');
        }
    }
}
void print(){
    for(int i = 1; i <= n; i++){
        printf("%s\n", s[i] + 1);
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            printf("dp[%d][%d] = %d   ", i, j, dp[i][j]);
        }
        putchar('\n');
    }

}
bool check(int x, int y){
    if(x > n || y > m) return false;
    return true;
}
int get(int x1, int y1, int x2, int y2){
    return dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1];
}
int main(){
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; i++){
        scanf("%s", s[i] + 1);
    }
    solve();
    //print();
    int ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            int x, y; x = i + k - 1; y = j + k - 1;
            if(!check(x, y)) continue;
            if(get(i, j, x, y)) ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}