说白了,深搜就是递归的加强版
优先考虑深度,换句话说就是一条路走到黑,直到无路可走的情况下,才会选择回头,然后重新选择一条路
先看看迷宫问题的题目
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
答案一眼就能看出来是8,但是要计算机去试探、
思 路
1、一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
2、二维数组,起点为a[0][0]
3、在起点的那个人可以往上下左右试探,有一个顺序,可以顺时针,先往右边然后顺时针
4、每走过一个点,都要把那个点设置为已访问,也就是在路上做标记
5、到达下一个点的时候,和起点一样,都要向四个方向试探,如果无路可走则不考虑这个方向
6、第一步和第二步的时候都只能往下一个方向移动,到第三个点位的时候就多了选择,可以向右走也可以向下走,这边先向右走,往终点的方向走,形成第一条路线,路上以访问点的数量就是步数,这只是其中的一条路径,不一定是最短的
7、试探其他的路径,因此需要回溯,回溯是什么意思呢,并不是瞬移回到起点,而是从刚刚到达的终点往回走,此时路上还有做过的标记,走完一个点,就要把标记给摘掉,这道题没什么死路,如果有遇到死路,就要回退到路口处重新选择,标记不一定要全部摘掉,这些标记可以留下来当作下一条路径的标记
既然学了DFS,为何不用万能的STL容器去存呢
在做出来之前,先扩展一下,C++的STL容器queue
里面有如下可以被调用的函数
- empty(); 如果队列空则返回真
- push( (这个里面加入你需要加入的元素或者结构体) ); 在末尾加入一个元素
- front(); 返回第一个元素
- back();返回最后一个元素
- pop(); 删除第一个元素
- size();返回队列中元素的个数
定义一个队列之前,需要明确要定义什么队列,例如,结构体
queue<(结构体的名字)> (你定义的队列名字);
queue<node> M;
定义一个队列之后最好看一下这个队列是不是空的
队列函数使用样例
#include<iostream>
#include<queue>
using namespace std;
struct hou
{
int x,y;
char c;
};
int main()
{
hou m;
queue<hou > M;
if(!M.empty()) cout<<"完了,没地方存了";
for(int i=1;i<=100;i+=3)
{
m.x =i;
m.y =i+100;
m.c =i;
M.push(m);
cout<<"**"<<M.size()<<"**"<<endl;
}
while(!M.empty())
{
hou n;//用来记录读出来的东西;
n=M.front();
cout<<n.x<<'*'<<n.y<<'*'<<n.c<<'*'<<endl;
M.pop();
}
return 0;
}
这段代码是一个教程转来的
最后我还是用了BFS来写,没想到吧
广度搜索的好处就是能够找出来唯一解
先从最右下到左上用BFS遍历一遍,记录好到达每个节点的步数。
然后反过来,从左上开始搜索。
每次搜索之前记录的步数比当前节点步数少一的点,符合条件的便是要输出的点
废话不多说,直接上代码
#include<iostream>
#include<queue>//队列函数库
#include<string.h>
using namespace std;
int main()
{
queue<int>q;//定义一个int类型的队列q
int i,j,x,y;
int dx[4]={0,1,-1,0};//左右方向定义数组
int dy[4]={1,0,0,-1};//上下方向定义数组
int vis[5][5],map[5][5];
char ch[5][5];
for (i=0;i<5;i++)
for (j=0;j<5;j++)
cin>>ch[i][j];
//迷宫以二维字符数组的形式输入
int vx=0,vy=0;
q.push(4);//push的括号里面加所需要的元素,这里是4
q.push(4);//push的意思是在队列的末尾加上一个元素
memset(vis,0,sizeof(vis));
//memset函数使用方法
//memset(数组,赋给数组的值,数组的长度)
//数组的长度用sizeof函数计算
//这里的意思是这个二维数组全部赋初值0
//一般情况下,memset对于结构体清零比较有效
memset(map,0,sizeof(map));//同上
while (!q.empty())//指的是如果队列一直不为空则一直循环
{
vx=q.front();//front的意思是返回第一个元素
q.pop();//pop前缀是队列q,意思是删除队列q的第一个元素
vy=q.front();
q.pop();
if (vx==0&&vy==0)//当返回的元素删除完的时候停止循环
break;
for (i=1;i<4;i++)
{
x=vx+dx[i];
y=vy+dy[i];
if (!vis[x][y]&&ch[x][y]=='0'&&x>=0&&x<5&&y>=0&&y<5)
{
q.push(x);
q.push(y);
vis[x][y]=1;
map[x][y]=map[vx][vy]+1;
}
}
}
vx=0;vy=0;//归零
cout<<"(0, 0)"<<endl;
int k=0;
while(k!=map[0][0]-1)
{
for (i=0;i<3;i++)
{
x=vx+dx[i];
y=vy+dy[i];
if (map[x][y]==map[vx][vy]-1)
{
cout<<'('<<x<<", "<<y<<')'<<endl;//输出烤串,<<是签子
k++;
break;
}
}
vx=x;
vy=y;
}
cout<<"(4, 4)"<<endl;//最后一步终点肯定是(4,4)
return 0;
}

这篇博客介绍了如何使用深度优先搜索(DFS)和广度优先搜索(BFS)解决迷宫问题。作者首先解释了DFS的基本思想,即一条路走到黑,无路可走时回溯,然后详细阐述了实现DFS的步骤,并讨论了使用STL容器queue的优势。尽管最初打算使用DFS,但作者最终选择了BFS,因为BFS能确保找到唯一解。通过BFS,作者从右下角开始反向搜索,记录每个节点的步数,最后给出了实现BFS的代码示例。
1万+

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



