BFS(Breadth-First Search,广度优先搜索)的核心思路可以用一句话概括:
按“层级”逐层向外扩展搜索节点,直到找到目标或遍历完所有节点。
核心思想
使用队列(Queue)维护待访问节点的顺序。
- 先进先出的特性确保按照“层级”访问节点。
从起始节点出发,依次访问其所有邻居节点。 - 再从这些邻居节点出发,访问它们的邻居节点(也就是“下一层”)。
记录已访问节点,避免重复访问。
BFS 的基本步骤
假设用 BFS 遍历一个图或解决搜索类问题,步骤如下:
将起始节点放入队列,并标记为已访问。
当队列不为空时:
- 弹出队首节点。
- 检查是否满足目标条件(如是,返回结果)。
- 将所有未访问过的邻居节点加入队列,并标记为已访问。
BFS解决迷宫最短路径问题
给定一个 n×m的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中:
0表示可以走的路;1表示不可通过的墙壁。
最初,有一个人位于左上角 (1,1)(1,1)(1,1) 处,已知该人每次可以向 上、下、左、右 任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 (n,m)(n, m)(n,m) 处,至少需要移动多少次。
题目保证:
- (1,1)和 (n,m) 处的数字为
0; - 且一定至少存在一条通路。
输入格式
- 第一行包含两个整数 n 和 m。
- 接下来 n 行,每行包含 m 个整数(
0或1),表示完整的二维数组迷宫。
输出格式
- 输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤n,m≤100
输入样例
5 5
0 0 1 0 0
1 0 1 0 1
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例
8
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e4;
typedef pair<int , int> PI;
int mp[N][N],mark[N][N],n,m;
int disk[4][2]={
{-1,0},
{1,0},
{0,-1},
{0,1}
};
#define check(x,y) (x>=0&&x<n&&y>=0&&y<m)
void bfs(int n,int m)
{
memset(mark,-1,sizeof mark);
queue <PI> q;
int start_x = 0;
int start_y = 0;
q.push({start_x,start_y});
mark[0][0]=0;
while(!q.empty())
{
PI top = q.front();
q.pop();
for(int i=0;i<4;i++)
{
int next_x = top.first+disk[i][0];
int next_y = top.second+disk[i][1];
if(check(next_x,next_y)&&mark[next_x][next_y]==-1&&mp[next_x][next_y]==0)
{
mark[next_x][next_y] = mark[top.first][top.second]+1;
q.push({next_x,next_y});
}
}
}
cout<<mark[n-1][m-1];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>mp[i][j];
}
}
bfs(n,m);
}
代码详解
int disk[4][2]={
{-1,0},
{1,0},
{0,-1},
{0,1}
};
初始化方向向量 上下左右
使得目标在二维数组中上下左右的移动
#define check(x,y) (x>=0&&x<n&&y>=0&&y<m)
边界定义 判断目标是否跑出(nxm)二维数组的范围
memset(mark,-1,sizeof mark);
queue <PI> q;
mark数组初始化 mark作用在于记录该位置是否走过 没有走过则为-1
定义pair类型的队列q
int start_x = 0;
int start_y = 0;
q.push({start_x,start_y});
mark[0][0]=0;
将目标初始位置放入队列
while(!q.empty())
{
PI top = q.front();
q.pop();
for(int i=0;i<4;i++)
{
int next_x = top.first+disk[i][0];
int next_y = top.second+disk[i][1];
if(check(next_x,next_y)&&mark[next_x][next_y]==-1&&mp[next_x][next_y]==0)
{
mark[next_x][next_y] = mark[top.first][top.second]+1;
q.push({next_x,next_y});
}
}
}
while 作用在于广搜的开始和结束
for 作用在于对于目标4个方向开始向下搜索,满足条件就使用mark记录,步长加1并加入队列
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>mp[i][j];
}
}
bfs(n,m);
}
主函数是对输入做一个记录形成一个地图
怎么实现的最短路径
mark[next_x][next_y] = mark[top.first][top.second]+1;
很好理解 就是下一步来源于上一步,并且走过的地方不会再走一遍,这确定了唯一性,使得到达终点路径最短
可总结一个基本模板:
int disk[][]={}; //根据实际设置方向向量
void bfs()
{
queue<Type>q; //根据实际设置类型
int start;
push(start); //入队
while(!q.empty)
{
int top = q.front();
q.pop(); //出队
for(){
//方向选择
if() //边界条件判断
{
//根据题目进行设计
}
}
}
}
2280

被折叠的 条评论
为什么被折叠?



