个人对深度优先搜索和广(宽)度优先搜索的理解

来源:互联网 发布:kcf跟踪算法原理 编辑:程序博客网 时间:2024/05/18 22:10

迷宫的最短路径

给定一个大小为N*M的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动。请求出从起点到终点所需的最小步数。请注意本题假定一定有一条道路可达。


N = 10 , M = 10 (迷宫如下图所示。‘#’,‘*’,‘s',‘e’分别表示墙壁,通道,起点和终点)

#s######*#
******#**#
*#*##*##*#
*#********
##*##*####
****#****#
*#######*#
****#*****
*####*###*
****#***e#


以前师兄给我说过深搜和广搜,可是当时的确没怎么听懂,这个暑假又回过头来学习了一下,还算弄得比较懂了。

所谓深搜就是一条道走到黑,直到没有路可走了才回头,个人理解就是“钻牛角尖”。

深搜就是从最开始的点依次往下搜索,然后将已经找过的点标记为已找过往下继续搜索,找不到的话就还原路径



#include <cstdio>
#include <cstdlib>
#define INF 10000000
#define maxi 10000
using namespace std;
char a[maxi][maxi];
int ans = INF;
int drv[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};//4个方向依次搜索
int n,m;




void dfs(int x,int y,int step)  
{
if (a[x][y] == 'e'){
ans = ans < step?ans:step;
return ;
}
a[x][y] = '#';//将这个点标记为已将找过。。
for (int i = 0;i< 4;i++){
int nx = x + drv[i][0],ny = y + drv[i][1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && a[nx][ny] != '#'){
dfs(nx,ny,step+1);
}
}
a[x][y] = '*';//如果没有找到e 并且不能再往下面搜索,就将路径还原。
}


int main()
{
scanf("%d%d",&n,&m);
for (int i = 0;i <n;i++)
{
scanf("%s",a[i]);
getchar();
}
int sx,sy;
for (int i = 0;i < n;i++)
{
for (int j = 0;j < m;j++)
{
if (a[i][j] == 's') sx = i,sy = j;
}
}
dfs(sx,sy,0);
printf("%d\n",ans);
system("pause");
return 0;
}




广度优先搜索就是想波浪一样一层一层的往外搜索,广搜通常需要用到优先队列。


#include <cstdio>
#include <cstdlib>
#include <queue>
#include <utility>
#define INF 10000000
#define maxi 10000
using namespace std;
typedef pair<int ,int > P;//类似与一个结构体。
char a[maxi][maxi];
int d[maxi][maxi];//到各个位置的最短距离的数组。
int dx[4][2] = {{1,0},{0,1},{0,-1},{-1,0}}; // 方向数组。
int n,m,sx,sy,ex,ey;//起点坐标和终点坐标。


int bfs()
{
queue<P> que;
for (int i = 0;i < n;i++)
for (int j = 0;j <m;j++)
d[i][j] = INF;//把所有位置都初始化为INF
//将起点加入队列,并把这一地点的距离设置为0;
que.push(P(sx,sy));
d[sx][sy] = 0;
//不断循环直到队列的长度为0
while(que.size()){
P p = que.front();que.pop();
if (p.first == ex && p.second == ey){
break;
}
//四个方向循环。
for (int i = 0;i < 4;i++){
int nx = p.first + dx[i][0],ny = p.second + dx[i][1];//所求的点。
if (0 <= nx && nx < n && 0 <= ny && ny < m && a[nx][ny] != '#' && d[nx][ny] == INF /*当前点并没有被访问。*/){
//可以移动的话,则加入到队列,并且到该位置的距离确定为到p的距离+1。
que.push(P(nx,ny));
d[nx][ny] = d[p.first][p.second] + 1;//在上一个点的基础上加一。
}
}
}
return d[ex][ey];
}


int main()
{
scanf("%d%d",&n,&m);
for (int i = 0;i <n;i++){
scanf("%s",a[i]);
}
for (int i = 0;i <n;i++){
for (int j = 0;j < n;j++){
if (a[i][j] == 's') sx = i,sy = j;
if (a[i][j] == 'e') ex = i,ey = j;
}
}
printf("%d",bfs());


system("pause");
return 0;
}


广搜和深搜一样都会遍历所有能够遍历到的状态,因此需要对所有状态进行处理是使用广搜也是可以的,但是递归函数可以很简短地编写,而且状态的管理也更简单所以

大多数情况下还是用深搜实现。反之,在求取最短路是深搜要反复经过同样的状态,所以此时还是使用广搜较好。


0 0
原创粉丝点击