bfs+二维前缀和
bfs求每个居民区最近的距离
然后二维前缀和优化一下就过了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int a[1010][1010],b[1010][1010],v[1010][1010],dis[1000010][3];
int t,n,r,sum,head,tail;
const int dx[]={0,0,0,1,-1};
const int dy[]={0,1,-1,0,0};
int abs(int x)
{
if(x>0)
return x;
return -x;
}
int minn(int x)
{
return min(x,n);
}
int maxn(int x)
{
return max(x,0);
}
void bfs()
{
do
{
head++;
for(int i=1; i<=4; i++) //二分求距离
{
int xx=dis[head][1]+dx[i];
int yy=dis[head][2]+dy[i];
if(xx<0||xx>n||yy<0||yy>n||v[xx][yy])
continue;
tail++;
v[xx][yy]=1;
dis[tail][1]=xx;
dis[tail][2]=yy;
b[xx][yy]=b[dis[head][1]][dis[head][2]]+1;
}
}
while(head<tail);
return;
}
int main()
{
freopen("city.in","r",stdin);
freopen("city.out","w",stdout);
scanf("%d",&t);
for(int i=1; i<=t; i++)
{
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
memset(v,0,sizeof(v));
scanf("%d%d",&n,&r);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
scanf("%d",&a[i][j]);
a[i][j]++;
if(a[i][j]==2)
{
tail++;
dis[tail][1]=i;
dis[tail][2]=j;
v[i][j]=1;
}
}
bfs();
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1]; //二维前缀和
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
printf("%d ",b[minn(i+r)][minn(j+r)]-b[maxn(i-r-1)][minn(j+r)]-b[minn(i+r)][maxn(j-r-1)]+b[maxn(i-r-1)][maxn(j-r-1)]); //输出,类似二维前缀和的区域求和。
cout<<endl;
}
cout<<endl;
}
return 0;
}