jzoj 2137. 【GDKOI2004】城市统计(bfs+前缀和)

2137. 【GDKOI2004】城市统计

Description

  中山市的地图是一个n*n的矩阵,其中标号为1的表示商业区,标号为0的表示居民区。为了考察市内居民区与商业区的距离,并对此作出评估,市长希望你能够编写一个程序完成这一任务。
  居民区i到商业区的距离指的是到距离它最近的商业区j的距离(|Xi-Xj|+|Yi-Yj|),而你将统计的是对于城市中的每一个区域k,以它为中心,所有满足max(|Xk-Xm|,|Yk-Ym|)<=r的区域m到商业区距离之和。结果同样以n*n的矩阵形式输出。

Input

  第一行为t,表示以下有t组数据,每组数据之间以空行隔开,以下:

   第一行为n,r(1<=r< n<=150)   
第二行起为一个n*n的矩阵。

Output

  t组n*n的矩阵。每组用空行隔开

Sample Input

Sample Input1:
1
4 1
1 0 0 0
1 1 0 0
0 1 1 0
0 1 0 0

Sample Input2:
2
10 4
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 1 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1

10 9
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1

Sample Output

Sample Output1:
1 4 9 8
2 5 10 9
2 4 7 7
2 3 4 4

Sample Output2:
40 50 57 63 70 70 63 57 50 40
50 60 68 76 86 86 76 68 60 50
57 68 76 85 97 97 85 76 68 57
63 76 85 94 107 107 94 85 76 63
70 86 97 107 120 120 107 97 86 70
70 86 97 107 120 120 107 97 86 70
63 76 85 94 107 107 94 85 76 63
57 68 76 85 97 97 85 76 68 57
50 60 68 76 86 86 76 68 60 50
40 50 57 63 70 70 63 57 50 40

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

分析:先用bfs算出每个居民点到商业区的距离,然后前缀和统计即可。

代码

#include <cstdio>
#define N 200
using namespace std;

int dx[5]={0,-1,0,1,0};
int dy[5]={0,0,1,0,-1};
int a[N][N],b[N][N],c[N][N],ans[N][N],n,r;
int s[50000][4],f[N][N];

int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}

bool check(int x,int y,int q)
{
    if (f[x][y]==q) return false;
    if (x<1||x>n||y<1||y>n) return false;
    return true;
}

int bfs(int x,int y,int q)
{
    int h,t;
    h=0;t=1;
    s[1][1]=x;
    s[1][2]=y;
    s[1][3]=0;
    while (h<t)
    {
        h++;
        for (int i=1;i<=4;i++)
            if (check(s[h][1]+dx[i],s[h][2]+dy[i],q))
            {
                t++;
                s[t][1]=s[h][1]+dx[i];
                s[t][2]=s[h][2]+dy[i];
                s[t][3]=s[h][3]+1;
                f[s[t][1]][s[t][2]]=q;
                if (a[s[t][1]][s[t][2]]==1) return s[t][3];
            }
    }
    return 0;
}

int main()
{
//  freopen("data10.in","r",stdin);
    int T;
    scanf("%d",&T);
    while (T--)
    {
    scanf("%d%d",&n,&r);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  
        {
            scanf("%d",&a[i][j]);
            b[i][j]=c[i][j]=f[i][j]=0;
        }
    int tot=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        if (a[i][j]==0)
        {
            tot++;
            b[i][j]=bfs(i,j,tot);
        }
    c[1][1]=b[1][1];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            c[i][j]=c[i-1][j]+c[i][j-1]+b[i][j]-c[i-1][j-1];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            int l1=max(1,i-r);
            int r1=min(n,i+r);
            int l2=max(1,j-r);
            int r2=min(n,j+r);
            ans[i][j]=c[r1][r2]-c[r1][l2-1]-c[l1-1][r2]+c[l1-1][l2-1];
        }
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
            printf("%d ",ans[i][j]);
        printf("\n");
    }
    printf("\n");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值