最稳的BFS写法是用std::queue,配合方向数组和严格的越界检查;避免vector模拟队列、stack误用、方向数组错位及访问前未检查等常见错误。

用 std::queue 实现 BFS,别手写队列
广度优先搜索在 C++ 里最稳的写法就是靠 std::queue,不是 std::deque 也不是自己写链表——前者多出不必要接口,后者容易越界或漏清空。BFS 的核心是“一层层往外扩”,std::queue 的 FIFO 特性天然匹配这个逻辑。
常见错误:用 vector 模拟队列,每次 erase(begin()) 导致 O(n) 删除,10⁴ 个点就卡死;或者用 stack 写成 DFS 却以为是 BFS。
- 初始化时只 push 起点,别把所有可走点一股脑塞进去
- 每轮 while 循环前先记下当前队列 size(
int sz = q.size()),用来控制“这一层”处理多少个节点 - 访问邻居前务必检查坐标是否越界、是否已访问、是否为障碍(比如迷宫中值为
1的墙)
迷宫二维数组里怎么算上下左右邻居
别硬写四组 x+1, y、x-1, y……这种代码难读还容易漏改。用方向数组更干净,也方便后期改成八连通或加权重。
典型坑:方向数组写成 {1,0,0,1,-1,0,0,-1} 却忘了两两一组取,导致 dx[i] 和 dy[i] 错位;或者没限制行列范围,x + dx[i] == -1 就直接去查 grid[-1][y] —— 这不是越界,是未定义行为。
立即学习“C++免费学习笔记(深入)”;
- 推荐写法:
const vector<pair>> dirs = {{-1,0},{0,-1},{1,0},{0,1}};</pair> - 检查必须放在访问前:
if (nx >= 0 && nx = 0 && ny - 如果迷宫用字符表示(如
'#'是墙),条件就得换成grid[nx][ny] != '#'
怎么记录路径长度或最短步数
BFS 天然保证第一次到达某点时步数最少,所以不需要额外比较大小,但得让每个节点知道自己离起点多远。最简方式不是给每个点存一个 dist[x][y] 数组(虽然可行),而是利用 BFS 的层序特性,在每层处理完后递增一个全局步数变量。
容易忽略的点:起点步数是 0 还是 1?题目说“从起点出发算第一步”,那起点初始化为 0,第一次扩展邻居才算第 1 步;如果题干说“起点本身算第 1 步”,那就初始化为 1。别凭感觉,看输入样例输出。
- 推荐结构:
int steps = 0;放在 while 外,每次处理完一层(for 循环结束)就steps++ - 如果要返回具体路径,得额外维护
parent[x][y]或用struct Node { int x, y, step; };把步数打包进队列 - 遇到终点立即 return
steps,别等队列空——否则可能多跑一层
边界情况一碰就崩:空迷宫、起点即终点、无解
本地测通了,交上去 RE 或 WA?大概率栽在边界上。C++ 不做运行时维度检查,grid[0].size() 在空 grid 下会崩溃;起点坐标非法(比如 -1,-1)也不报错,但访问就段错误。
真实比赛/练习里,70% 的 WA 来自没处理好“根本走不到终点”。BFS 结束后队列空了,但你没检查是否真的抵达终点,就直接返回 -1 或默认值,而有些题要求输出特定字符串(如 "No Path")。
- 开头先判
if (grid.empty() || grid[0].empty()) return -1; - 起点坐标要检查:
if (sx = n || sy = m || grid[sx][sy] == 1) - while 结束后加一句:
return -1;(如果题目要无解返回 -1),别忘了这行











