目录:
题目:
分析:
我们可以先跑一遍
bfs
b
f
s
,然后用二位前缀和求解~~
讲下前缀和数组:
ans
a
n
s
ans[i][j]
a
n
s
[
i
]
[
j
]
代表前i行的前j列的总和
而
ans[i][j]=ans[i−1][j]+ans[i][j−1]−ans[i−1][j−1]+f[i][j]
a
n
s
[
i
]
[
j
]
=
a
n
s
[
i
−
1
]
[
j
]
+
a
n
s
[
i
]
[
j
−
1
]
−
a
n
s
[
i
−
1
]
[
j
−
1
]
+
f
[
i
]
[
j
]
为什么要减去
ans[i−1][j−1]
a
n
s
[
i
−
1
]
[
j
−
1
]
呢?
是因为我们前面进行加法时有重复的部分
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
queue<int>x,y;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int f[151][151],ans[151][151],c[151][151];
int n;
void bfs()
{
while(!x.empty())
{
for(int i=0;i<4;i++)
{
int xx=x.front()+dx[i],yy=y.front()+dy[i];
if(xx<1||yy<1||xx>n||yy>n||c[xx][yy]==1) continue;
c[xx][yy]=1;
f[xx][yy]=f[x.front()][y.front()]+1;
x.push(xx);y.push(yy);
}
x.pop();y.pop();
}
return;
}
int main()
{
int t=read(),a,bx,by,sx,sy;
for(int i=1;i<=t;i++)
{
memset(f,0,sizeof(f));
memset(ans,0,sizeof(ans));
n=read();int r=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
c[i][j]=read();
if(c[i][j]) x.push(i),y.push(j);
}
bfs();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans[i][j]=ans[i-1][j]+ans[i][j-1]+f[i][j]-ans[i-1][j-1];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
bx=min(n,i+r);by=min(n,j+r);
sx=max(0,i-r-1);sy=max(0,j-r-1);
printf("%d ",ans[bx][by]-ans[bx][sy]-ans[sx][by]+ans[sx][sy]);
}
printf("\n");
}
printf("\n");
}
return 0;
}