为啥bfs走迷宫的路程是最小值而dfs就不一定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥bfs走迷宫的路程是最小值而dfs就不一定相关的知识,希望对你有一定的参考价值。

参考技术A 首先,bfs是每走一步,就把所有可能的下一步走法存入数组。然后数组指针向后移一位,也就是说bfs是把所有可能的走法全部同时走一遍,也就是说在同一时刻,走法的数组里还未判断的位置已经走过的步数是相同的(或者只差1),这样一来,当抵达终点后,那一个算法一定是走的步数最少的。
而dfs是把一条路走到底再换另一条,你可以想象一下,一条很绕的路碰巧走到终点,dfs就判断为计算出来了,当然不是最短本回答被提问者和网友采纳
参考技术B bfs是发散状的各种走法同时走,第一个成功的一定是最快成功的,dfs是某一条路走到底第一个成功的不一定是最优的路线

百炼3752:走迷宫--栈实现dfs

 

3752:走迷宫

总时间限制: 
1000ms
 
内存限制: 
65536kB
描述
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
输入
第一行是两个整数,R和C,代表迷宫的长和宽。( 1<= R,C <= 40)
接下来是R行,每行C个字符,代表整个迷宫。
空地格子用\'.\'表示,有障碍物的格子用\'#\'表示。
迷宫左上角和右下角都是\'.\'。
输出
输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。
样例输入
5 5
..###
#....
#.#.#
#.#.#
#.#..
样例输出
9


【分析】 本题用递归实现起来不方便,因此用一个结构模拟走迷宫的过程:
1 struct node {
2     int x,y;    //节点坐标
3     int step;   //到达该节点需要的步数
4     node(int x,int y,int step) : x(x),y(y),step(step) {};
5 };

 

此处,node表示迷宫中的一个“节点”。

用栈实现dfs走迷宫的思想:(1) 将起始节点入栈;

          (2) 将起始节点出栈,作为“当前所在的节点”

          (3) 将“当前所在的节点”所能到达的所有节点入栈(这便是下一步所有的路);

          (4) 栈顶节点出栈,作为下一步的“当前所在的节点”

          (5) 重复上述过程,直到走到终点。

由于栈后进先出的特点,因此每一个出栈作为“当前所在的节点”的节点一定是上一步刚刚入栈的节点(即上一步的“当前所在的节点”所能直接到达的某个下一
步的节点),因此栈实现的是dfs(而非bfs)。

【代码】
 1 #include <iostream>
 2 #include <stack>
 3 using namespace std;
 4 
 5 const int maxr = 45;
 6 const int maxc = 45;
 7 char board[maxr][maxc];
 8 bool visited[maxr][maxc];
 9 int R,C;
10 int mov[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
11 
12 struct node {
13     int x,y;    //节点坐标
14     int step;   //到达该节点需要的步数
15     node(int x,int y,int step) : x(x),y(y),step(step) {};
16 };
17 
18 bool check(int x,int y)
19 {
20     if( x <= R && x >= 1 && y <= C && y >= 1 && board[x][y] == \'.\'
21        && !visited[x][y] )
22         return true;
23     return false;
24 }
25 
26 int dfs(int x,int y)
27 {
28     stack<node> s;
29     node start(x,y,1);
30     s.push(start);
31 
32     //栈仅是工具,真正的动态dfs过程从while循环中才开始,
33     //从栈中取出一个节点,相当于确定了目前所在的节点
34     while( !s.empty() ) {
35         node cur = s.top();
36         s.pop();
37 
38         //以下for循环把当前能到达的所有点入栈
39         for( int i=0; i<4; i++ ) {
40             int ix = cur.x + mov[i][0];
41             int iy = cur.y + mov[i][1];
42             if( !check(ix,iy) ) continue;
43 
44             node nxt(ix,iy,cur.step+1); //创造下一个合法节点
45 
46             //判断:如果已经到目标点直接返回答案
47             if( nxt.x == R && nxt.y == C ) {
48                 return nxt.step;    //(1)
49             }
50             visited[nxt.x][nxt.y] = true;     //不加这句,会导致已走过的节点多次入栈,造成死循环
51             //入栈了的节点今后一定都能访问到,因此不用担心漏掉"可走的路"
52             s.push(nxt);
53         }
54     }
55 
56     return -1;  //若栈中所有节点都已经取出,程序走到了此处(而不是在(1)处返回),
57                 //说明终点无法走到
58 }
59 
60 int main()
61 {
62     cin >> R >> C;
63     for( int i=1; i<=R; i++ ) {
64         for( int j=1; j<=C; j++ ) {
65             cin >> board[i][j];
66         }
67         getchar();  //除行尾回车
68     }
69     int ans = dfs(1,1);
70 
71     cout << ans << endl;
72     return 0;
73 }

本题使用bfs实现也可以,只需要把栈换成队列就行了。

以上是关于为啥bfs走迷宫的路程是最小值而dfs就不一定的主要内容,如果未能解决你的问题,请参考以下文章

第四届河南省省赛 走迷宫 二分+DFS

ybt 1252 广度优先搜索 走迷宫(二维最小步数)

poj 3026 Borg Maze(最小生成树+bfs)

算法浅谈——走迷宫问题与广度优先搜索

[北大机试C]:走迷宫(BFS)

DFS之奇偶剪枝