[JZOJ2137] 城市统计

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

Summary

  先用bfs算出每个居民区距离最近商业区的距离,再求二位前缀和:f[j][k]=f[j][k]-f[j-1][k-1]+f[j-1][k]+f[j][k-1]

  那么以(k,j)为中心,边为2*e正方形的值为:f[min(m,j+e)][min(m,k+e)]+f[max(0,j-e-1)][max(0,k-e-1)]-f[min(m,j+e)][max(0,k-e-1)]-f[max(0,j-e-1)][min(m,k+e)]

  注意边界范围

Code

 1 #include<cstdio>
 2 using namespace std;
 3 int t,m,l[4],r[4],a[200][200],f[200][200],dy[1000000][2],e;
 4 int max(int x,int y)
 5 {
 6     if (x>y) return x;
 7     return y;
 8 }
 9 int min(int x,int y)
10 {
11     if (x>y) return y;
12     return x;
13 }
14 int main()
15 {
16     l[1]=0;l[2]=0;l[3]=1;l[4]=-1;
17     r[1]=1;r[2]=-1;r[3]=0;r[4]=0;
18     scanf("%d",&t);
19     for (int i=1;i<=t;i++)
20     {    
21         int tot=0,ans=1;
22         scanf("%d%d",&m,&e);
23         for (int j=1;j<=m;j++)
24             for (int k=1;k<=m;k++)
25                 f[j][k]=0xffffff;
26         for (int j=1;j<=m;j++)
27             for (int k=1;k<=m;k++)
28             {
29                 scanf("%d",&a[j][k]);
30                 if (a[j][k]==1)
31                 {
32                     tot++;
33                     dy[tot][1]=j;
34                     dy[tot][2]=k;
35                     f[j][k]=0;
36                 }
37             }
38         while (ans<=tot)
39         {
40             for (int j=1;j<=4;j++)
41             {
42                 int z=dy[ans][1]+l[j],g=dy[ans][2]+r[j];
43                 if (z>=1&&g>=1&&z<=m&&g<=m)
44                     if (f[z][g]>f[dy[ans][1]][dy[ans][2]]+1)
45                     {
46                         f[z][g]=f[dy[ans][1]][dy[ans][2]]+1;
47                         tot++;
48                         dy[tot][1]=z;
49                         dy[tot][2]=g;
50                     }
51             }
52             ans++;
53         }
54         for (int j=1;j<=m;j++)
55             for (int k=1;k<=m;k++)
56                 f[j][k]=f[j][k]-f[j-1][k-1]+f[j-1][k]+f[j][k-1];                
57         for (int j=1;j<=m;j++)
58         {
59             for (int k=1;k<=m;k++)
60                 printf("%d ",f[min(m,j+e)][min(m,k+e)]+f[max(0,j-e-1)][max(0,k-e-1)]-f[min(m,j+e)][max(0,k-e-1)]-f[max(0,j-e-1)][min(m,k+e)]);
61             printf("\n");
62         }
63         printf("\n");
64     }
65 }
View Code

 

 

posted @ 2018-07-16 10:24  kasiruto  阅读(56)  评论(0编辑  收藏