题意:

给定一个 的二维矩阵,每个位置为 0 或者 1。
询问所有 的子矩阵中存在 的矩阵个数。

解法:

二维前缀和。

先从一维说起, 个元素的一维数组为 ,下标从
那么对应的前缀和数组 的定义为:

求前缀和的递推式为:

代码实现:

s[0] = 0;
for(int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];

利用前缀和,我们可以 求一段区间 的和。

再到二维前缀和:

求二维前缀和的递推式为:

求一个子矩阵 的和为:

会二维前缀和,那么这道题就结束了。
先求出二维前缀和,然后遍历所有 的子矩阵,判断和是否非零,统计答案。

Code:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, m, k, a[N][N], s[N][N];
int main() {
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            scanf("%1d", &a[i][j]);
            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
        }
    int ans = 0;
    for(int i = k; i <= n; i++)
        for(int j = k; j <= m; j++) {
            int v = s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k];
            if(v) ans++;
        }
    printf("%d\n", ans);
    return 0;
}