题目链接:https://www.luogu.org/problemnew/show/P2335
【题目描述】
现在我们给出一个
的单色位图,且该图中至少含有一个白色的像素。我们用
来代表第
行第
列的像素,并且定义两点
和
之间的距离为:
。
对于每个像素,计算出离该像素最近的白色像素与它的距离。
【输入格式】
第一行包括两个用空格分开的整数
和
。以下的
行每行包括一个长度为
的整数为
或
,在第
行的第
个字符如果为
,那么表示像素
为白的,否则为黑的。
【输出格式】
输出一个
的数表,其中的第
行的第
个数字为
表示像素
到最近的白色像素的距离。
【输入样例】
3 4
0 0 0 1
0 0 1 1
0 1 1 0
【输出样例】
3 2 1 0
2 1 0 0
1 0 0 1
【数据规模】
, 。
【题解】
对于每个白色像素 并更新。时间复杂度 。
将所有白色像素连接到同一个源点, 。时间复杂度 。
我的神奇的解法:
考虑 的情况。将每个白色像素往左右分别更新,遇到白色像素则停止(想一想,为什么)。
每行进行这样的更新,接着每列也进行同样的操作。输出即可。
为什么这个算法是正确的呢?因为得到AC了。
每个白色像素更新行内所有能更新的点,再让它们更新所有网格内的点,此时不可能再用这个点更新了。因为这样走的是最短路(=行距离+列距离)。
注:这份代码是最优解,因为它省去了 需要的队列空间。
【代码】
#include<cstdio>
int n,m,a[155][155];
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) {
scanf("%d",&a[i][j]);
a[i][j]?a[i][j]=0:a[i][j]=1e9;
}
for (int i=1;i<=n;i++) {
for (int j=1;j<m;j++) if (a[i][j]+1<a[i][j+1]) a[i][j+1]=a[i][j]+1;
for (int j=m;j>1;j--) if (a[i][j]+1<a[i][j-1]) a[i][j-1]=a[i][j]+1;
}
for (int i=1;i<=m;i++) {
for (int j=1;j<n;j++) if (a[j][i]+1<a[j+1][i]) a[j+1][i]=a[j][i]+1;
for (int j=n;j>1;j--) if (a[j][i]+1<a[j-1][i]) a[j-1][i]=a[j][i]+1;
}
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++) printf("%d ",a[i][j]);
puts("");
}
return 0;
}