2020 winter vacation [gmoj1598] [GDKOI2004] [city statistics city] [BFS + interval prefix and]

Title description

The map of Zhongshan City is an n * n matrix, where the number 1 indicates a commercial area and the number 0 indicates a residential area. In order to investigate the distance between the residential area and the commercial area in the city and make an assessment of this, the mayor hopes that you can write a program to accomplish this task. The distance from the residential area i to the commercial area refers to the distance to the closest commercial area j (| Xi-Xj | + | Yi-Yj |) (you can understand that their ranks are different), and you will The statistics are the sum of the distances from all residential areas to commercial areas in the matrix area of ​​(2 * r + 1) * (2 * r + 1) matrix centered on it for each area k in the city. The result is also output in the form of n * n matrix.

Input

The first line is t, indicating that there are t sets of data below, and each set of data is separated by a blank line. The following: the
first line is n, r (1 <= r <n <= 150) and the
second line is an n * The matrix of n.

Output

t groups of n * n matrices. Each group is separated by a blank line

Sample input

1
4 1
1 0 0 0
1 1 0 0
0 1 1 0
0 1 0 0

Sample output

1 4 9 8
2 5 10 9
2 4 7 7
2 3 4 4

analysis

Damn t group data, the game broke 0 and thought that he could laugh too violently. . .
Forget about Xian Kang Kang's ultra-violent practices (70pts), five-fold cycle aa.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int t,n,r,a[160][160],f[160][160],ans,sum,dis;
int main()
{
	freopen("city.in","r",stdin);
	freopen("city.out","w",stdout);
	memset(f,127,sizeof(f));
    cin>>t;
    for(register int k=1;k<=t;k++)
    {
	    cin>>n>>r;
    	memset(a,0,sizeof(a));
    	memset(f,127,sizeof(f));
    	for(register int i=1;i<=n;i++)
	    {
	    	for(register int j=1;j<=n;j++)
	    	{
	    		scanf("%d",&a[i][j]);
	    		if(a[i][j]==1)
	    		{
	    			for(register int x=1;x<=n;x++)
	    			{
	    				for(register int y=1;y<=n;y++)
	    				{
	    					dis=abs(x-i)+abs(y-j);
	    					f[x][y]=min(f[x][y],dis);
						}
					}
				}
			}
		}
		for(register int i=1;i<=n;i++)
		{
			for(register int j=1;j<=n;j++)
			{
				sum=0;
				for(register int x=i-r;x<=i+r;x++)
				{
					for(register int y=j-r;y<=j+r;y++)
					{
						if(x>0&&y>0&&x<=n&&y<=n) sum+=f[x][y];
					}
				}
				a[i][j]=sum;
			}
		}
		for(register int i=1;i<=n;i++)
		{
			for(register int j=1;j<=n;j++)
			{
				printf("%d ",a[i][j]);
			}
			printf("\n");
		}
		printf("\n");
	}
	fclose(stdin);
	fclose(stdout);
    return 0;
}

Then come to the positive solution.
In fact, you can find that bfs is a good choice. You can find the nearest 1 at a time and mark the distance. Just O (n 2 ).
Because the sum is required, the interval prefix and ans [i] [j] are used to represent the sum of the matrix from (1,1) to (i, j), and then the answer is qwq after subtraction. Pay attention to special boundaries.

Code on

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int t,n,r,f[160][160],ans[160][160],a[160][160]; 
const int dx[5]={0,1,0,-1,0};
const int dy[5]={0,0,-1,0,1};
queue<int> x,y;
void bfs()
{
	while(!x.empty())
	{
		for(int i=1;i<=4;i++)
		{
			int xx=x.front()+dx[i];
			int yy=y.front()+dy[i];
			if(xx>0&&xx<=n&&yy>0&&yy<=n&&a[xx][yy]==0)
			{
				a[xx][yy]=1;
				f[xx][yy]=f[x.front()][y.front()]+1;
				x.push(xx);
				y.push(yy);
			}
		}
		x.pop();
		y.pop();
	}
}
int main()
{
	freopen("city.in","r",stdin);
	freopen("city.out","w",stdout); 
    cin>>t;
    for(int k=1;k<=t;k++)
    {
    	memset(f,0,sizeof(f));
    	memset(ans,0,sizeof(ans));
    	cin>>n>>r;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++) 
    		{
    			cin>>a[i][j];
    			if(a[i][j]==1)
    			{
    				x.push(i);
    				y.push(j);//压入队列 
				}
			} 
		}
		bfs();
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1]+f[i][j];
			}
			/*计算区间前缀和qwq*/
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				int lx=min(n,i+r),ly=min(n,j+r),rx=max(0,i-r-1),ry=max(0,j-r-1);
				cout<<ans[lx][ly]+ans[rx][ry]-ans[rx][ly]-ans[lx][ry]<<' ';
			}
			cout<<endl;
	    }
	    cout<<endl;
	}
	fclose(stdin);
	fclose(stdout);
    return 0;
}

Published 110 original articles · 100 praises · 8013 visits

Guess you like

Origin blog.csdn.net/dglyr/article/details/105080479