
第二课《迷宫王国大冒险------二维 BFS》
🌟一、故事开始:迷宫王国的宝藏
1、很久以前,在:
🏰「迷宫王国」里,
藏着一颗神秘宝石。
2、小骑士阿勇接到了任务:
找到宝藏!
3、可是问题来了:
迷宫里:
有墙壁
有陷阱
有死胡同
4、而且:
阿勇必须走最短路线!
5、于是,他想:
"这次不能用 DFS 乱冲了!"
因为:
DFS 容易:
一条路冲到底
结果绕远路。
6、这次应该使用BFS的方法:
于是他按照BFS方法,上路了。
🌟二、今天同学们要学什么?
今天是:
🌟二维 BFS!
上一课:
我们在一维"数字线"上移动。
今天:
我们进入:
🗺️二维地图!
🌟三、认识地图坐标
1、假设地图长这样:
S . . #
# . . .
. . # E
2、这里:
S = 起点
E = 终点
# = 墙
. = 可以走
3、🌟地图中的位置怎么表示?
使用:
坐标!
4、例如:
(行, 列)
比如:
(1) 左上角:
(0,0)
(2) 终点:
(2,3)
🌟四、在地图里怎么移动?
小骑士每次可以:
⬆️上
⬇️下
⬅️左
➡️右
这叫:
四方向移动
🌟五、方向数组
这是 BFS 的经典的技巧!
1、🌟方向数组
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
2、🌟什么意思?
(1)第0个方向
(-1, 0)
表示:
向上走
(2)第1个方向
(1, 0)
表示:
向下走
(3)第2个方向
(0, -1)
表示:
向左走
(4)第3个方向
(0, 1)
表示:
向右走
🌟六、BFS 如何搜索迷宫?
1、假设阿勇在:
(0,0)
2、BFS 会:
(1)第1层
搜索:
一步能到的位置。
(2)第2层
搜索:
两步能到的位置。
(3)第3层
搜索:
三步能到的位置。
3、像不像:
🌊水波扩散?
🌟七、为什么 BFS 一定最短?
这是今天最核心的问题!
1、因为:
BFS 是按层搜索的!
2、它的搜索方式:
第一层:
1步到达
第二层:
2步到达
第三层:
3步到达
.......
3、所以:
第一次到终点,
一定是最少步数!
4、这就是:
BFS 最强大的地方!
🌟八、visited 二维数组
1、上一课:
我们用:
vis[x]
2、今天地图是二维的。
所以:
vis[x][y]
3、表示:
(x,y) 是否来过
4、🌟为什么必须有 visited?
否则:
阿勇会这样:
左 → 右 → 左 → 右
无限绕圈!
🌟九、地图越界问题(初学者易错!)
1、假设地图大小:
n 行
m 列
2、合法位置必须满足:
0 <= x < n
0 <= y < m
3、否则:
就会:
🚫走出地图!
🌟十、第一道迷宫题
1、🎮题目
地图:
S . . #
# . . .
. . # E
2、要求:
求最少步数
🌟十一、BFS 参考程序
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
int x;
int y;
int step;
};
char mp[105][105];
bool vis[105][105];
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int main()
{
int n = 3;
int m = 4;
// 地图
char temp[3][4] =
{
{'S','.','.','#'},
{'#','.','.','.'},
{'.','.','#','E'}
};
// 复制地图
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
mp[i][j] = temp[i][j];
}
}
queue<Node> q;
// 起点
q.push({0,0,0});
vis[0][0] = true;
while(!q.empty())
{
Node cur = q.front();
q.pop();
int x = cur.x;
int y = cur.y;
// 到达终点
if(mp[x][y] == 'E')
{
cout << "最少步数:" << cur.step << endl;
return 0;
}
// 枚举四个方向
for(int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
// 判断是否合法
if(nx >= 0 && nx < n &&
ny >= 0 && ny < m &&
!vis[nx][ny] &&
mp[nx][ny] != '#')
{
vis[nx][ny] = true;
q.push({nx, ny, cur.step + 1});
}
}
}
cout << "无法到达终点" << endl;
return 0;
}
🌟十二、程序执行过程
1、开始:
(0,0)
进入队列。
2、然后扩展:
(0,1)
3、再扩展:
(1,1)
(0,2)
4、继续:
像水波一样。
5、最终:
第一次到达:
E
时,
一定最短!
🌟十三、二维 BFS 模板
🌊二维 BFS 四步法
第一步
起点入队。
第二步
取出队头。
第三步
枚举四个方向。
第四步
合法就入队。
🌟十四、新手易犯的错误
❌错误1:忘记 visited
会无限循环。
❌错误2:忘记判断边界
数组越界。
❌错误3:墙壁也进入队列
必须:
mp[nx][ny] != '#'
❌错误4:step 不加1
下一层步数必须:
cur.step + 1
🌟十五、什么时候想到二维 BFS?
以后看到:
1、🏰迷宫
2、🛣️最短路径
3、🚶最少移动次数
4、🌊扩散问题
5、🔥火焰蔓延
6、🦠病毒感染
🌟就要想到:
BFS!是不是可以!
⚔️十六、课堂挑战题 ⚔️
🎮挑战1
地图:
S . #
. . .
# . E
求最少步数。
🎮挑战2
如果:
小骑士还能:
斜着走
怎么办?
提示:
方向数组要改成:
八方向!
🌟十七、本课总结
1、🌊二维 BFS 的本质:
在地图上进行层层扩散!
2、📦BFS 的核心工具:
queue 队列
3、🧭方向数组:
专门处理移动方向
4、🚪第一次到终点:
一定最短!
5、🛑visited 必不可少:
防止重复进入!
🌟今天同学们真正学会的:
不只是走迷宫的方法。
而要掌握:
"地图中的最短路思维"。