对于之前走迷宫的那个题
回忆一下dfs的代码
#include <bits/stdc++.h>
using namespace std;
int a[110][110];
bool check[110][110];
int n,m;
int ans=1e9;
int nxt[4][2]={{1,0},{0,-1},{-1,0},{0,1}};
void dfs(int x,int y,int step){
if(x==n&&y==m){
ans=min(ans,step);
return;
}
for(int i=0;i<4;i++){
int nx=x+nxt[i][0];
int ny=y+nxt[i][1];
if(check[nx][ny]==1||nx<1||nx>n||ny<1||ny>m||check[nx][ny]==true){
continue;
}else{
check[nx][ny]=true;
dfs(nx,ny,step+1);
check[nx][ny]=false;
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
check[1][1]=true;
dfs(1,1,0);
cout<<ans;
}
我们是用dfs解决的,当时只是为了练习dfs的思想和熟练度,但一但地图大,方案变多,dfs就会超时。一个20*20的矩阵dfs能跑几十分钟,原因就是在dfs的回溯上,dfs算法里每个点会被遍历多次,这大大浪费了我们的时间 。
这道题的正解应该是用bfs来做,bfs时间短的原因就在于它每个点只遍历一次(还不一定遍历所有点,到目标点他就跳出循环了)。
bfs的算法我们是用队列这一数据结构实现的,为什么要用队列呢,这和这个算法的核心思想密切相关,bfs的核心就在于对当前能走到的所有点进行扩展,然后再对第一次扩展到的点找到它所能到达的所有点进行扩展,不断从起点扩展这个图直到扩展到终点。注意,在扩展完当前点能走到的所有点以后这个点就可以不要了,我们始终保留站在地图最前沿的那一批开拓者,看开拓者的位置是否为终点即可(因为一个点只要进行开拓操作,那它就一定不是终点,否则直接跳出循环就不去开拓了),不断开拓直到找到终点
这里推荐一个b站的视频模拟该过程模拟的非常好:BFS广搜解决迷宫问题_哔哩哔哩_bilibili
代码也没用到晦涩难懂的二元组之类的,很简单的结构体队列
我们结合这道题对bfs进行讲解,注释写的很明白(自认为)
#include <bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N];//存储地图数据
int n,m;//读入行数,列数
bool check[N][N];//防止往回走的check数组
struct point{/*结构体存储开拓者的坐标和这是第几次开拓到达的点(见过用二元组写的但是感觉结构体更好看懂)*/
int x;
int y;
int step;
};
queue<point> aa;//定义结构体队列
int nex[4][2]={{1,0},{0,-1},{-1,0},{0,1}};//往右,下,左,上四个方向走的情况
int flag;//记录终点到达不了的情况
void bfs(){
while(!aa.empty()){//队列非空就还能开拓,队列空了还没找到答案就是没有通往终点的路
point t=aa.front();//取出队头元素对他进行扩展(用t承接着方便操作)
if(t.x==n&&t.y==m){//找到终点了
flag=1;
cout<<t.step;
return;
}
for(int i=0;i<4;i++){//分别尝试向四个方向扩展
int nx=t.x+nex[i][0];
int ny=t.y+nex[i][1];
if(check[nx][ny]==true||a[nx][ny]==1||nx<1||nx>n||ny<1||ny>m){/*排除一切不符合情况的走法:走回头路,超出边界,撞到障碍物*/
continue;
}else{ //满足扩展条件,入队
point temp;//用个临时结构体承接一下要入队的数据(将数据规范整合成结构体的形式再塞入队列中)
temp.x=nx,temp.y=ny,temp.step=t.step+1;
aa.push(temp);
check[nx][ny]=true;
}
}
//扩展完当前队头能走的所有点后队头元素没用了(用过了),出队
aa.pop();
}
if(flag==0) cout<<-1;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
//初始化队列
point start;
start.x=1;start.y=1;start.step=0;
aa.push(start);
check[1][1]=true;
bfs();
}
最后不得不再次感叹不同数据结构的强大