P2335 [SDOI2005] 位图(洛谷详解)

文章讲述了如何运用BFS算法在给定的位图中找到每个像素到最近白色像素的最短距离,涉及编程实现和数据结构应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好!那个又双叒叕菜又双叒叕爱玩我回来了

今天!我为大家上演BFS

之,

位图

题目描述

现在我们给出一个 n   × m n\ \times m n ×m 的单色位图,且该图中至少含有一个白色的像素。我们用 ( i , j ) (i,j) (i,j) 来代表第 i i i 行第 j j j 列的像素,并且定义两点 p 1 = ( i 1 , j 1 ) p_1=(i_1,j_1) p1=(i1,j1) p 2 = ( i 2 , j 2 ) p_2=(i_2,j_2) p2=(i2,j2) 之间的距离为:

d ( p 1 , p 2 ) = ∣ i 1 − i 2 ∣ + ∣ j 1 − j 2 ∣ d(p_1,p_2)=|i_1-i_2|+|j_1-j_2| d(p1,p2)=i1i2+j1j2

任务

请写一个程序,读入该位图,并对于每个像素,计算出离该像素最近的白色像素与它的距离。把结果输出。

输入格式

第一行包括两个用空格分开的整数 n n n m m m 1 ≤ n ≤ 150 1 \le n \le 150 1n150 1 ≤ m ≤ 150 1 \le m \le 150 1m150

以下的 n n n 行每行包括一个长度为 m m m 的整数为 0 0 0 1 1 1,在第 i + 1 i+1 i+1 行的第 j j j 个字符如果为 1 1 1,那么表示像素 ( i , j ) (i,j) (i,j) 为白的,否则为黑的。

输出格式

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

样例 #1

样例输入 #1

3 4
0 0 0 1
0 0 1 1
0 1 1 0

样例输出 #1

3 2 1 0
2 1 0 0
1 0 0 1

解题思路:这道一可以用bfs来写,白的是1,黑的是0;暴力的去找白点到黑点的最小值,就是白点到黑点的最少步数。

图例:
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n, m;
char s[183][183];//地图
bool vis[183][183];//标记数组
int dx[5] = { 0, 1, -1, 0, 0 };//方向数组
int dy[5] = { 0, 0, 0, 1, -1 };
int a[183][183];
struct node {
    ll x, y, step;//横坐标,纵坐标,步数
} o;
int find(ll x, ll y) {//bfs
    queue<node> f;
    f.push((node){ x, y, 0 });
    vis[x][y] = true;
    while (!f.empty()) {
        o = f.front();
        f.pop();
        for (int i = 1; i <= 4; i++) {
            int xx = o.x + dx[i];//向四周拓展每一个点
            int yy = o.y + dy[i];
            if (s[xx][yy] == '1') { // 如果找到了,返回
                a[x][y] = o.step + 1;
                return 0;
            }
            if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && vis[xx][yy] == false) {//判断是否在地图里
                f.push((node){ xx, yy, o.step + 1 });
                vis[xx][yy] = true;//如果在入队,标记已被走过
            }
        }
    }
}
int main() {
    scanf("%lld %lld", &n, &m);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> s[i][j];
        }
    }//输入
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (s[i][j] == '0')
                find(i, j);
             //找的过程
            for (int k = 1; k <= n; k++) {
                for (int l = 1; l <= m; l++) {
                    vis[k][l] = false;
                }
            }//每一次再找完后要把标记数组清空,不然会出问题
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            printf("%lld ", a[i][j]);
        }
        printf("\n");
    }//输出结果
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值