题目描述
中山市的地图是一个nn的矩阵,其中标号为1的表示商业区,标号为0的表示居民区。为了考察市内居民区与商业区的距离,并对此作出评估,市长希望你能够编写一个程序完成这一任务。 居民区i到商业区的距离指的是到距离它最近的商业区j的距离(|Xi-Xj|+|Yi-Yj|)(你可以理解为他们的行列分别作差),而你将统计的是对于城市中的每一个区域k,以它为中心的(2r+1)(2r+1)的矩阵区域内所有居民区到商业区的距离总和。结果同样以n*n的矩阵形式输出。
输入
第一行为t,表示以下有t组数据,每组数据之间以空行隔开,以下:
第一行为n,r(1<=r<n<=150)
第二行起为一个n*n的矩阵。
输出
t组n*n的矩阵。每组用空行隔开
样例输入
1
4 1
1 0 0 0
1 1 0 0
0 1 1 0
0 1 0 0
样例输出
1 4 9 8
2 5 10 9
2 4 7 7
2 3 4 4
解题思路
先做一遍BFS把每个点到最近商店的距离求出来
再用前缀和求出每个点所在矩阵的距离和求出
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int way[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,m,x,v[500100][2],h,t,f[200][200],ans,a[200][200],xx,yy;
bool check(int x,int y){
return (x>0&&x<=n&&y>0&&y<=n);
}
void BFS(){
while(h++<t){
for(int i=0;i<4;i++){
xx=v[h][0]+way[i][0],yy=v[h][1]+way[i][1];
if(check(xx,yy)&&!f[xx][yy]&&a[xx][yy]<1){
f[xx][yy]=f[v[h][0]][v[h][1]]+1;
v[++t][0]=xx,v[t][1]=yy;
}
}
}
}
int main(){
freopen("city.in","r",stdin);
freopen("city.out","w",stdout);
int T;
scanf("%d",&T);
while(T--){
memset(f,0,sizeof(f));
scanf("%d%d",&n,&m);
h=0,t=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==1)
v[++t][0]=i,v[t][1]=j;
}
BFS();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]+=f[i][j-1]+f[i-1][j]-f[i-1][j-1];
for(int i=1;i<=n;i++,printf("\n")){
for(int j=1;j<=n;j++){
ans=f[min(i+m,n)][min(j+m,n)];
ans+=f[max(i-m-1,0)][max(j-m-1,0)]-f[max(i-m-1,0)][min(j+m,n)]-f[min(i+m,n)][max(j-m-1,0)];
printf("%d ",ans);
}
}
printf("\n");
}
}