时间限制:10000ms
单点时限:
1000ms
内存限制:
256MB
描述
给定一个N x M的01矩阵,其中1表示陆地,0表示水域。对于每一个位置,求出它距离最近的水域的距离是多少。
矩阵中每个位置与它上下左右相邻的格子距离为1。
输入
第一行包含两个整数,N和M。
以下N行每行M个0或者1,代表地图。
数据保证至少有1块水域。
对于30%的数据,1 <= N, M <= 100
对于100%的数据,1 <= N, M <= 800
输出
输出N行,每行M个空格分隔的整数。每个整数表示该位置距离最近的水域的距离。
4 4 0110 1111 1111 0110样例输出
0 1 1 0 1 2 2 1 1 2 2 1 0 1 1 0
思路:
方法很多 如BFS,最短路,本文使用DP方法解决。
因为找水路距离最近,权值均衡,所以不可能绕圈。
那么只需DP四个方向(左上->右下,右下->左上,左下->右上,右上->左下)
状态转移方程为,来的两种方向相邻一格+1及本身取最小值。
如 左上-> 右下: dp[i][j] = min( dp[i][j], min( dp[i-1][j] , dp[i][j-1] ) + 1 ) //(+1放外面快了1ms(ಥ_ಥ) ,也可能早上评测姬比较快)
代码:
#include<stdio.h>
#include<string.h>
#define For(a,b,c) for(int a = b; a <= c; a++)
char maze[805][805];
int dp[805][805];
int minn(int a, int b)
{
return a < b ? a :b;
}
int main()
{
int N, M;
scanf("%d%d",&N,&M);
For(i,1,N) scanf("%s",maze[i]+1);
memset(dp,0x3f,sizeof(dp));
For(i,1,N) For(j,1,M) if(maze[i][j] == '0') dp[i][j] = 0;
For(i,1,N)
{
For(j,1,M)
{
dp[i][j] = minn(dp[i][j], minn(dp[i-1][j], dp[i][j-1])+1 ); //左上
dp[N-i+1][j] = minn(dp[N-i+1][j], minn(dp[N-i+2][j], dp[N-i+1][j-1])+1 ); //左下
dp[i][M-j+1] = minn(dp[i][M-j+1], minn(dp[i-1][M-j+1], dp[i][M-j+2])+1 ); //右上
dp[N-i+1][M-j+1] = minn(dp[N-i+1][M-j+1], minn(dp[N-i+2][M-j+1], dp[N-i+1][M-j+2])+1 ); //右下
}
}
For(i,1,N)
{
for(int j = 1; j < M; j++)
printf("%d ",dp[i][j]);
printf("%d\n",dp[i][M]);
}
return 0;
}