题目链接
题意:
有
一
个
n
∗
m
的
01
矩
阵
,
1
代
表
有
石
块
有一个n*m的01矩阵,1代表有石块
有一个n∗m的01矩阵,1代表有石块
帕
秋
莉
可
以
在
其
中
任
意
一
个
k
∗
k
的
正
方
形
区
域
施
法
帕秋莉可以在其中任意一个k*k的正方形区域施法
帕秋莉可以在其中任意一个k∗k的正方形区域施法
但
是
如
果
区
域
中
有
石
块
那
么
则
不
能
施
法
但是如果区域中有石块那么则不能施法
但是如果区域中有石块那么则不能施法
问
有
多
少
种
情
况
不
能
施
法
问有多少种情况不能施法
问有多少种情况不能施法
题解:
其
实
,
问
题
说
的
就
是
这
个
n
∗
m
矩
阵
中
其实,问题说的就是这个n*m矩阵中
其实,问题说的就是这个n∗m矩阵中
找
k
∗
k
的
正
方
形
,
所
有
的
正
方
形
中
有
几
个
是
包
含
1
的
找k*k的正方形,所有的正方形中有几个是包含1的
找k∗k的正方形,所有的正方形中有几个是包含1的
所
以
可
以
算
这
个
k
∗
k
正
方
形
里
数
的
和
是
多
少
所以可以算这个k*k正方形里数的和是多少
所以可以算这个k∗k正方形里数的和是多少
如
果
大
于
0
说
明
里
面
有
1
如果大于0说明里面有1
如果大于0说明里面有1
但
是
这
道
题
数
据
范
围
,
n
,
m
<
=
1
e
3
,
k
<
=
m
i
n
(
n
,
m
)
但是这道题数据范围,n,m<=1e3,k<=min(n,m)
但是这道题数据范围,n,m<=1e3,k<=min(n,m)
我
们
能
用
的
最
高
复
杂
度
就
是
O
(
n
m
)
我们能用的最高复杂度就是O(nm)
我们能用的最高复杂度就是O(nm)
所
以
我
们
想
要
算
矩
阵
,
需
要
借
助
一
下
二
维
前
缀
和
计
算
所以我们想要算矩阵,需要借助一下二维前缀和计算
所以我们想要算矩阵,需要借助一下二维前缀和计算
二
维
前
缀
和
其
实
就
是
从
点
(
1
,
1
)
到
(
n
,
m
)
这
个
矩
阵
的
所
有
和
二维前缀和其实就是从点(1,1)到(n,m)这个矩阵的所有和
二维前缀和其实就是从点(1,1)到(n,m)这个矩阵的所有和
算
法
就
是
先
用
(
n
−
1
,
m
)
+
(
n
,
m
−
1
)
+
a
[
n
]
[
m
]
算法就是先用(n-1,m)+(n,m-1)+a[n][m]
算法就是先用(n−1,m)+(n,m−1)+a[n][m]
把
(
1
,
1
)
到
(
n
−
1
,
m
)
和
(
1
,
1
)
到
(
n
,
m
−
1
)
的
矩
阵
画
出
来
把(1,1)到(n-1,m)和(1,1)到(n,m-1)的矩阵画出来
把(1,1)到(n−1,m)和(1,1)到(n,m−1)的矩阵画出来
我
们
会
发
现
有
这
个
重
叠
部
分
我们会发现有这个重叠部分
我们会发现有这个重叠部分
那
就
是
(
1
,
1
)
到
(
n
−
1
,
m
−
1
)
,
直
接
减
去
这
一
部
分
即
可
那就是(1,1)到(n-1,m-1),直接减去这一部分即可
那就是(1,1)到(n−1,m−1),直接减去这一部分即可
这
样
就
直
接
算
出
来
了
二
维
前
缀
和
这样就直接算出来了二维前缀和
这样就直接算出来了二维前缀和
然
后
我
们
就
可
以
枚
举
正
方
形
块
,
看
他
的
k
∗
k
矩
阵
然后我们就可以枚举正方形块,看他的k*k矩阵
然后我们就可以枚举正方形块,看他的k∗k矩阵
k
∗
k
矩
阵
就
是
用
二
维
前
缀
和
操
作
一
下
k*k矩阵就是用二维前缀和操作一下
k∗k矩阵就是用二维前缀和操作一下
我
枚
举
的
正
方
形
是
正
方
形
右
下
角
的
点
,
所
以
这
个
矩
阵
如
下
我枚举的正方形是正方形右下角的点,所以这个矩阵如下
我枚举的正方形是正方形右下角的点,所以这个矩阵如下
s
u
m
[
i
]
[
j
]
−
s
u
m
[
i
−
k
]
[
j
]
−
s
u
m
[
i
]
[
j
−
k
]
+
s
u
m
[
i
−
k
]
[
j
−
k
]
sum[i][j]-sum[i-k][j]-sum[i][j-k]+sum[i-k][j-k]
sum[i][j]−sum[i−k][j]−sum[i][j−k]+sum[i−k][j−k]
用
这
个
点
的
二
维
前
缀
和
,
减
去
左
边
多
出
的
,
和
上
边
多
出
的
用这个点的二维前缀和,减去左边多出的,和上边多出的
用这个点的二维前缀和,减去左边多出的,和上边多出的
会
发
现
两
个
多
出
的
部
分
重
叠
了
一
个
小
正
方
形
,
加
上
多
减
去
的
即
可
会发现两个多出的部分重叠了一个小正方形,加上多减去的即可
会发现两个多出的部分重叠了一个小正方形,加上多减去的即可
代码如下
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
char g[1010][1010];
int sum[1010][1010];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>g[i][j];
if(g[i][j]=='1')sum[i][j]++;
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
for(int i=k;i<=n;i++)
for(int j=k;j<=m;j++){
int cnt=sum[i][j]-sum[i-k][j]-sum[i][j-k]+sum[i-k][j-k];
if(cnt>0)ans++;
}
cout<<ans<<endl;
return 0;
}