中文名是宽度优先搜索,也叫广度优先搜索。
是图上最基础、最重要的搜索算法之一。
所谓宽度优先。就是每次都尝试访问同一层的节点。 如果同一层都访问完了,再访问下一层。
这样做的结果是,BFS 算法找到的路径是从起点开始的 最短 合法路径。换言之,这条路径所包含的边数最小。
在 BFS 结束时,每个节点都是通过从起点到该点的最短路径访问的。
算法过程可以看做是图上火苗传播的过程:最开始只有起点着火了,在每一时刻,有火的节点都向它相邻的所有节点传播火苗。
一般用队列实现,也就是从队列 Q 中取出队首的节点 u,然后把与 u 相邻的所有节点 v 标记为已访问过并放入队列 Q,以此可以储存“传播火苗”后的状态。
比如这道题,可以想到所有‘1’的距离B都是0,由于BFS 算法找到的路径是从起点开始的 最短 合法路径,那么初始时便可以把这些‘1’的点全部入队,之后把符合条件的点的距离更新后继续入队
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1005;
const int MOD = 998244353;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int dx[4] = {-1, 1, 0, 0}
, dy[4] = { 0,0, -1, 1 };
char a[maxn][maxn];
int b[maxn][maxn];
int n, m;
int fx, fy;
struct My {
int x; int y;
};
queue<My>q;
void bfs() {
while (!q.empty()) {
My t = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int tx = t.x + dx[i], ty = t.y + dy[i];
if (b[tx][ty] != -1)
continue;
if (tx >= 0 && tx < n && ty >= 0 && ty < m) {
b[tx][ty] = b[t.x][t.y] + 1;
q.push({ tx,ty });
}
else
continue;
}
}
}
inline void solve() {
cin >> n >> m;
for (int i = 0; i< n; i++) {
cin >> a[i];
}
memset(b, -1, sizeof b);
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++) {
if (a[i][j] == '1') {
b[i][j] = 0;
q.push({ i,j });
}
}
}
bfs();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << b[i][j] << ' ';
}
cout << '\n';
}
return;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
std::cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}