当前位置:   article > 正文

c++:DFS与BFS详解_dfs和bfs c++

dfs和bfs c++

DFS(深度优先搜索):从某个状态开始,不断转移状态到无法转移为止,然后退回到前一步,继续转移到其他状态,不断重复,直至找到最终的解。

         总是从最开始的状态出发,遍历所有的可到达状态。隐式利用栈进行计算

eg:有一个N*M的田,雨后积水,八连通(下图相对w的*部分)的积水被认为连在一起,请给出园里有多少水洼?

      ***

      *w*

      ***

  input :3 3  

***

*w*

w**

 output: 1


  解析:从任意w开始,不停把w邻接部分用*代替,复杂度O(N*M)

  1. int n, m;
  2. char field[max_n][max_m+1];
  3. //现在的位置
  4. void dfs(int x, int y)
  5. {
  6. field[x][y] = '*';
  7. for (int dx = -1; dx <= 1; dx++)
  8. {
  9. for (int dy = -1; dy <= 1; dy++)
  10. {
  11. int nx = x + dx, ny = y + dy;
  12. if (0 < nx&&nx < n && 0 < ny&&ny < m&&field[nx][ny] == 'W')
  13. dfs(nx, ny);
  14. }
  15. }
  16. return ;
  17. }
  18. void solve()
  19. {
  20. int count = 0;
  21. for (int i = 0; i < n; i++)
  22. for (int j = 0; j < m; j++)
  23. if (field[n][m] == 'W')
  24. {
  25. dfs(i, j);
  26. count++;
  27. }
  28. printf("d%\n", count);
  29. }

BFS(宽度优先搜索)总是先搜索距离初始状态近的状态,利用队列进行运算。复杂度O(状态数*转移的方式)

给定一个大小为N*M的迷宫,由通道('.')和墙壁('#')组成,其中通道S表示起点,通道G表示终点,每一步移动可以达到上下左右中不是墙壁的位置。试求出起点到终点的最小步数。(本题假定迷宫是有解的)(N,M<=100)

样例输入:

10 10

样例输出:

22


解析:bfs中,对于已经访问过得状态用标记管理,本例用INF标记,并初始化d数组,这样到达终点就会终止搜索,可如果一直下去直到队列为空,就可以计算出各个地点的

最 短距离。

  1. #include <iostream>
  2. #include <queue>
  3. using namespace std;
  4. const int MAX_N = 100;
  5. const int MAX_M = 100;
  6. const int INF = 0x3f3f3f3f;
//用pair表示状态时,用typedef更方便一些
typedef pair<int, int> P;
  1. char maze[MAX_N][MAX_M + 1];
  2. int N, M;
  3. int sx, sy; //起点的位置
  4. int gx, gy; //终点的位置
  5. int d[MAX_N][MAX_M];//储存起点到某一点的距离
  6. int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 }; //表明每次x和y方向的位移
  7. void bfs()
  8. {
  9. queue<P> que;
  10. for (int i = 0; i < N; i++)
  11. for (int j = 0; j < M; j++)
  12. d[i][j] = INF; //初始化所有点的距离为INF
  13. que.push(P(sx, sy));
  14. d[sx][sy] = 0; //从起点出发将距离设为0,并放入队列首端
  15. while (que.size()) //题目保证有路到终点,所以不用担心死循环
  16. {
  17. P p = que.front(); que.pop();//弹出队首元素
  18. int i;
  19. for (i = 0; i < 4; i++)
  20. {
  21. int nx = p.first + dx[i];
  22. int ny = p.second + dy[i];//移动后的坐标
  23. //判断可移动且没到过
  24. if (0 <= nx&&nx < N
  25. && 0 <= ny&&ny < M
  26. &&maze[nx][ny] != '#'
  27. &&d[nx][ny] == INF)//之前到过的话不用考虑,因为距离在队列中递增,肯定不会获得更好的解
  28. {
  29. que.push(P(nx, ny)); //可以移动则设定距离为之前加一,放入队列
  30. d[nx][ny] = d[p.first][p.second] + 1;
  31. if(nx==gx && ny==gy) break;
  32. }
  33. }
  34. if(i!=4) break;
  35. }
  36. }
  37. int main()
  38. {
  39. cin>>N>>M;
  40. for (int i = 0; i < N; i++)
  41. cin>>maze[i];
  42. for (int i = 0; i < N; i++)
  43. for (int j = 0; j < M; j++)
  44. {
  45. if (maze[i][j] == 'S')
  46. {
  47. sx = i; sy = j;
  48. }
  49. if (maze[i][j] == 'G')
  50. {
  51. gx = i; gy = j;
  52. }
  53. }
  54. bfs();
  55. cout<<d[gx][gy]<<endl;
  56. return 0;
  57. }

总结:bfs与dfs两种都能生成所有遍历状态,但是要求对所有状态进行处理时使用dfs比较方便;在求最短路径用bfs比较好。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/995223
推荐阅读
相关标签
  

闽ICP备14008679号