[SDOI2005] 位图(bit)

题目链接:https://www.luogu.org/problemnew/show/P2335

【题目描述】
现在我们给出一个 n × m 的单色位图,且该图中至少含有一个白色的像素。我们用 ( i , j ) 来代表第 i 行第 j 列的像素,并且定义两点 p 1 = ( i 1 , j 1 ) p 2 = ( i 2 , j 2 ) 之间的距离为: d ( p 1 , p 2 ) = | i 1 i 2 | + | j 1 j 2 |

对于每个像素,计算出离该像素最近的白色像素与它的距离。

【输入格式】
第一行包括两个用空格分开的整数 n m 。以下的 n 行每行包括一个长度为 m 的整数为 0 1 ,在第 i + 1 行的第 j 个字符如果为 1 ,那么表示像素 ( i , j ) 为白的,否则为黑的。

【输出格式】
输出一个 n × m 的数表,其中的第 i 行的第 j 个数字为 f ( i , j ) 表示像素 ( i , j ) 到最近的白色像素的距离。

【输入样例】

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

【数据规模】

1 n 150 1 m 150

【题解】

  • 对于每个白色像素 B F S 并更新。时间复杂度 n 2 m 2

  • 将所有白色像素连接到同一个源点, B F S 。时间复杂度 n m

  • 我的神奇的解法:

考虑 n = 1 的情况。将每个白色像素往左右分别更新,遇到白色像素则停止(想一想,为什么)。

每行进行这样的更新,接着每列也进行同样的操作。输出即可。

为什么这个算法是正确的呢?因为得到AC了。

每个白色像素更新行内所有能更新的点,再让它们更新所有网格内的点,此时不可能再用这个点更新了。因为这样走的是最短路(=行距离+列距离)。

注:这份代码是最优解,因为它省去了 B F S 需要的队列空间。

【代码】

#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;
}

猜你喜欢

转载自blog.csdn.net/orzzmh/article/details/80950796
BIT