BFS入门笔记
BFS入门笔记
BFS广度优先搜索,在处理问题时,优先考虑更多的机会,而不是像DFS那样优先走一条路,再回溯
BFS基于队列实现,目的是把可能的解放在同一层处理,即BFS队列中至多只有两层的解
考虑完前一层可能的解后,再考虑下一层的解。把当前解的后续解再放到队列尾部。
如上图中,BCDE
处在同一层考虑,那么考虑到 B
的后续解时,把FGH
放在 CDE
后面,即CDEFGH
,基于队列实现。
BFS每一层只往下走一步,当这一步的所有情况考虑完后,再考虑下一步的解
这里以洛谷P1443为例:
通过BFS解决问题,首先要引入队列这一数据结构
#include <queue>
处理坐标,这里使用构造结构体的方法,得到横纵坐标
struct pos { int x, y; };
定义队列,存储我们当前考虑的点(坐标位置)
queue<pos> p;
存储地图,一般分为已访问路径的图和存路径的图
int map[405][405], ans[405][405];
向量变量,本题中,马可走 “日” 字,则向量如下
int dx[] = { 1,2,2,1,-1,-2,-2,-1 }; int dy[] = { 2,1,-1,-2,-2,-1,1,2 };
BFS函数的写法:
void bfs(int sx, int sy) { memset(ans, -1, sizeof(ans)); p.push({ sx,sy }); ans[sx][sy] = 0; map[sx][sy] = 1; while (!p.empty()) { pos t = p.front(); p.pop(); for (int i = 0; i < 8; i++) { int tx = t.x + dx[i], ty = t.y + dy[i]; if (check(tx, ty)) { p.push({ tx,ty }); map[tx][ty] = 1; ans[tx][ty] = ans[t.x][t.y] + 1; } } } }
其中,我们先使 ans
数组的值全部初始化为 -1
即一开始所有的点走还没考虑(都走不到)。
将出发点 sx,sy
放进队列,从这个点开始考虑存在的解。
赋值 ans[sx][sy],map[sx][sy]
,初始时,出发点能够走到(走 \(0\) 步),且已经被走过。
当队列不空时,使用向量变量,计算下一步的位置。
check
函数检查下一步的位置是否合法
int check(int x, int y) { if (x<1 || x>n || y<1 || y>m) return 0;//越界非法 if (map[x][y]) return 0;//走到已走过的位置上非法 return 1; }
判断合法后,标记这个位置已经走到过 map[tx][ty] = 1
,且走到这个位置的步数为走到上一个点的步数加 \(1\) 步,ans[tx][ty] = ans[t.x][t.y] + 1
。
最后根据题意,输出我们的所有路径的地图即可
for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { printf("%d ", ans[i][j]); } printf("\n"); }
完整代码:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <queue> #include <cstring> #include <stdlib.h> using namespace std; struct pos { int x, y; }; int n, m, sx, sy; queue<pos> p; int map[405][405], ans[405][405]; int dx[] = { 1,2,2,1,-1,-2,-2,-1 }; int dy[] = { 2,1,-1,-2,-2,-1,1,2 }; int check(int x, int y) { if (x<1 || x>n || y<1 || y>m) return 0; if (map[x][y]) return 0; return 1; } void bfs(int sx, int sy) { memset(ans, -1, sizeof(ans)); p.push({ sx,sy }); ans[sx][sy] = 0; map[sx][sy] = 1; while (!p.empty()) { pos t = p.front(); p.pop(); for (int i = 0; i < 8; i++) { int tx = t.x + dx[i], ty = t.y + dy[i]; if (check(tx, ty)) { p.push({ tx,ty }); map[tx][ty] = 1; ans[tx][ty] = ans[t.x][t.y] + 1; } } } } int main() { scanf("%d %d %d %d", &n, &m, &sx, &sy); bfs(sx, sy); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { printf("%d ", ans[i][j]); } printf("\n"); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程