3.【GDKOI2004】城市统计(city)
题目描述
中山市的地图是一个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先找出各个点最近的商业区的距离,然后用二维前缀和快速输出答案
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int n,r,a,t;
long long head,tail,x[30005],y[30005],b[155][155];
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
void bfs()//bfs找距离
{
head=0;
while(head<tail)
{
head++;
for(int i=1;i<=4;i++)
{
int xx=x[head]+dx[i],yy=y[head]+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n)
if(b[xx][yy]>b[x[head]][y[head]]+1||b[xx][yy]==2147483647)
{
b[xx][yy]=b[x[head]][y[head]]+1;
tail++;
x[tail]=xx;
y[tail]=yy;
}
}
}
}
int main()
{
freopen("city.in","r",stdin);
freopen("city.out","w",stdout);
cin>>t;
while(t--)
{
tail=0;
cin>>n>>r;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
b[i][j]=2147483647;
cin>>a;
if(a==1){tail++;x[tail]=i;y[tail]=j;b[i][j]=0;}//将商业区成为起始点
}
bfs();
for(int i=1;i<=n;i++)//二维前缀和
for(int j=1;j<=n;j++)
b[i][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++)
{
int x1=i-r-1,y1=j-r-1,x2=i+r,y2=j+r;
x1=max(0,x1);//避免越界
y1=max(0,y1);
x2=min(n,x2);
y2=min(n,y2);
cout<<b[x2][y2]-b[x1][y2]-b[x2][y1]+b[x1][y1]<<' ';//通过二维前缀和输出
if(j==n)cout<<endl;
}
cout<<endl;
}
return 0;
}
下面附本次比赛的其它题目
2020.03.18模拟赛18(第一题)
2020.03.18模拟赛18(第二题)
2020.03.18模拟赛18(第三题)
2020.03.18模拟赛18(第四题)
2020.03.18模拟赛18(总结)