您的位置:首页 > 其它

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

2015-08-19 15:00 281 查看
迷宫的最短路径
给定一个大小为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;

}

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

大多数情况下还是用深搜实现。反之,在求取最短路是深搜要反复经过同样的状态,所以此时还是使用广搜较好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: