dfs+bfs总结(写的超级详细,看完绝不后悔!!!)---强推
核心思路
-
队列的使用:BFS 是一种逐层扩展的算法,因此使用队列
queue
来维护当前需要处理的节点,按顺序处理。每次从队列中取出一个节点,并将它的四个方向上的相邻节点加入队列中。 -
距离数组
dis
的使用:dis
用于记录从起点(1, 1)
到当前点的最短距离。每当从某个点移动到相邻的未访问过的点时,记录相邻点的距离为当前点的距离加 1。 -
地图边界检查与访问控制:在移动时,确保新的坐标
xn, yn
在矩阵边界内,并且没有访问过该点。 -
优化策略:一旦找到终点
(n, m)
,立即返回结果,避免进行不必要的搜索。
全局变量定义
const int N=110;
int n,m;
int tu[N][N]; // 用于表示地图,0 表示可通行,1 表示障碍
int dis[N][N]; // 用于记录到每个点的最短距离
typedef pair<int,int> PII; // 定义一个 pair,用于存储坐标 (x, y)
queue<PII> q; // BFS 使用的队列
tu[N][N]
:保存地图,其中 0 表示可以通行,1 表示障碍物。dis[N][N]
:保存到每个点的最短路径长度。queue<PII> q;
:定义一个队列,用于 BFS 的核心操作——存储需要处理的节点。
BFS函数实现
int bfs()
{
if(n==1&&m==1)
return 0;
memset(dis,-1,sizeof dis); // 初始化距离数组
q.push({1,1}); // BFS 从 (1,1) 开始
dis[1][1]=0; // 起点的距离为 0
int dx[4]={0,0,-1,1}; // x 方向的四个移动方向
int dy[4]={1,-1,0,0}; // y 方向的四个移动方向
while(!q.empty()) // 当队列不为空时,继续搜索
{
auto p=q.front();
q.pop(); // 弹出队首元素
int x=p.first,y=p.second; // 获取当前坐标
int xn,yn;
for(int k=0;k<4;k++) // 遍历四个方向
{
xn=x+dx[k]; // 计算新位置的 x 坐标
yn=y+dy[k]; // 计算新位置的 y 坐标
if(xn<=n && xn>=1 && yn>=1 && yn<=m && tu[xn][yn]==0 && dis[xn][yn]==-1)
{
dis[xn][yn] = dis[x][y] + 1; // 更新距离
if(xn==n && yn==m) return dis[xn][yn]; // 如果到达终点,返回距离
q.push({xn,yn}); // 将新位置加入队列
}
}
}
}
memset(dis,-1,sizeof dis)
:将dis
数组全部初始化为-1
,表示所有点都未被访问。q.push({1,1})
:将起点(1,1)
加入 BFS 队列,并设置起点的距离为0
。dx[4]
和dy[4]
:分别表示在x
轴和y
轴上移动的四个方向。- 在
while (!q.empty())
循环中,队列q
中存储的是当前层待处理的所有点,通过q.pop()
弹出队首元素,检查四个方向上的点:- 如果新点
(xn, yn)
在边界内(xn>=1 && xn<=n && yn>=1 && yn<=m
)。 - 该点是可以通行的(
tu[xn][yn]==0
),且没有被访问过(dis[xn][yn]==-1
)。 - 满足这些条件后,将其标记为已访问,距离为前一个点的距离加
1
,并将其加入队列。 - 如果
(xn, yn)
是终点(n, m)
,则返回其距离。
- 如果新点
主函数
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>tu[i][j]; // 读取地图
}
}
cout<<bfs()<<endl; // 输出最短距离
return 0;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int tu[N][N];
int dis[N][N];
typedef pair<int,int> PII;
queue<PII> q;
int bfs()
{
if(n==1&&m==1)
return 0;
memset(dis,-1,sizeof dis);
q.push({1,1});
dis[1][1]=0;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
while(!q.empty())
{
auto p=q.front();
q.pop();
int x=p.first,y=p.second;
int xn,yn;
for(int k=0;k<4;k++)
{
xn=x+dx[k];
yn=y+dy[k];
if(xn<=n&&xn>=1&&yn>=1&&yn<=m&&tu[xn][yn]==0&&dis[xn][yn]==-1)
{
dis[xn][yn]=dis[x][y]+1;
if(xn==n&&yn==m) return dis[xn][yn];
q.push({xn,yn});
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>tu[i][j];
}
}
cout<<bfs()<<endl;
return 0;
}