题目大意:
中山市的地图是一个的矩阵,其中标号为的表示商业区,标号为的表示居民区。居民区到商业区的距离指的是到距离它最近的商业区j的距离,而你将统计的是对于城市中的每一个区域,以它为中心,所有满足的区域m到商业区距离之和。
思路:
70分:
直接暴力求解即可。
100分:
首先在读入的时候,若这个点是商业区,就先将它入队,之后跑一边,求出每个居民区到商业区的距离(由于每个点只要访问1次,所以时间复杂度为),之后用二维前缀和加速,输出每个位置的答案。总时间复杂度为。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int dx[]={0,0,0,1,-1};
const int dy[]={0,1,-1,0,0};
int a[301][301],b[301][301],p[301][301],t,n,r,sum,head,tail,state[500001][3];
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=state[head][1]+dx[i];
int yy=state[head][2]+dy[i];
if (xx<0||xx>n||yy<0||yy>n||p[xx][yy]) continue;
tail++; //入队
p[xx][yy]=1;
state[tail][1]=xx;
state[tail][2]=yy;
b[xx][yy]=b[state[head][1]][state[head][2]]+1;
}
}
while (head<tail);
return;
}
int main()
{
scanf("%d",&t);
while (t--)
{
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
memset(p,0,sizeof(p));
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++; //入队
state[tail][1]=i;
state[tail][2]=j;
p[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)]);
putchar(10);
}
putchar(10);
}
return 0;
}