今天,咱们用简单易懂的语言,来讲讲广度优先搜索 BFS 喵!
用一句话来说 BFS 就是:“兄弟齐心,齐头并进,地毯式轰炸!”
1. 首先,可以把它想象成“搜救队”的故事
这次进入迷宫寻找宝藏的是一支训练有素的搜救队。他们手里带了一样神器:
一张排队名单(队列 Queue):用来记录接下来谁该去探路。原则特别公平,就是“先到先得,不准插队”喵。
他们是这样探险的:
- 第一步(扩散):队长站在起点看了眼周围:有上、下、左、右四条路!队长不偏心,派出 4 个队员,分别站在四条路的入口。然后把这 4 个位置写进排队名单里。
- 第二步(排队):名单里排在最前面的队员 A 先行动,他前迈一步,看看自己周围有哪些没走过的路,把这些新路又写到名单的末尾去排队。
- 第三步(轮流):队员 A 探完路,名单里的下个队员 B 开始迈出一步探路,同样把新发现的路加到队尾。
- 第四步(重复):重复执行第二步,直到找到求救人员或路线全部找完为止。
就这样,大家你走一步,我走一步,一层一层地向外平推。这种像水波纹一样扩散的搜索过程,在 C++ 里就叫 BFS 广度优先搜索。
2. BFS 的优缺点喵
- 优点(一定找到最短路):因为大家是齐头并进的,所以,搜救队只要第一次踩到宝藏,那条路径绝对是最短、最快的路线!这也是 BFS 最强大的地方喵。
- 缺点(超级费内存):因为要同时记录所有正在迷宫里蔓延的队员(排队名单会变得很长很长),如果迷宫很大,电脑的内存很容易被吃光爆掉(MLE)。
3. 那它 C++ 代码长什么样?
BFS 在 C++ 里最忠实的黄金搭档就是—— queue(队列)。
给大家看一个极简的代码骨架:
`C++这个函数的意思是:搜救队从 (startX, startY) 开始地毯式搜索
void bfs(int startX, int startY) {
queue<pair<int, int>> q; // 准备好排队名单
q.push({startX, startY}); // 把起点塞进名单
vis[startX][startY] = 1; // 标记起点已经有人占了
while (!q.empty()) { // 只要名单不为空,搜救就不停止
pair<int, int> current = q.front(); // 叫到名字的排头队员出来
q.pop(); // 离开队伍去探路
int x = current.first;
int y = current.second;
// 找到救援人员啦!
if (x == targetX && y == targetY) {
庆祝();
return; // 因为是 BFS,此时绝对是最短路径,直接结束!
}
// 瞧瞧四周(上下左右)
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 如果前面的格子能走,而且之前没被其他队员踩过
if (check(nx, ny) && !vis[nx][ny]) {
vis[nx][ny] = 1; // 赶紧插个旗子占领它,防止别人重复进去
q.push({nx, ny}); // 让新格子去名单末尾排队
}
}
}
}`
最后小结:
- DFS 深度优先:单人拿红线,一条路撞南墙(省内存,常用于凑步数、找所有方案)。
- BFS 广度优先:大部队排队,水波纹式平推(费内存,常用于地图里找最短路径喵)。