数据结构之图论之深搜广搜

ゞ 浴缸里的玫瑰 2022-05-12 09:04 365阅读 0赞

一、问题引入

有一天,小哈一个人去玩迷宫。但是方向感不好的小哈很快就迷路了。小哼得知后便去解救无助的小哈。此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈。那么,问题来了…

922928-20170825191830355-501498782.png

二、问题的分析

首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q)。其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径。

此时摆在小哼面前的路有两条,我们可以先让小哼往右边走,直到走不通的时候再回到这里,再去尝试另外一个方向。

在这里我们规定一个顺序,按照顺时针的方向来尝试(即右→下→左→上)。

922928-20170825195542152-1662666496.png

我们先来看看小哼一步之内可以到达的点有哪些?只有(1,2)和(2,1)。

根据刚才的策略,我们先往右边走,但右边(1,3)有障碍物,所以只能往下(2,2)这个点走。但是小哈并不在(2,2)这个点上,所以小哼还得继续往下走,直至无路可走或者找到小哈为止。

注意:并不是让我们找到小哈此题就解决了。因为刚才只是尝试了一条路的走法,而这条路并不一定是最短的。刚才很多地方在选择方向的时候都有多种选择,因此我们需要返回到这些地方继续尝试往别的方向走,直到把所有可能都尝试一遍,最后输出最短的一条路径。

例如下图就是一条可行的搜索路径:

922928-20170825200422339-125974986.png

这道题可以有两种解法,一种是dfs,一种是bfs。粘贴代码,首先是dfs:

20分钟hou ::::: 自己代码找不到了,分分钟手写一个:

  1. //广度优先搜索解救小哈
  2. //众所周知:深搜用栈广搜用队列。
  3. #include<bits/stdc++.h>
  4. using namespace std;
  5. int a[51][51],v[51][51],m,n,p,q,minn=9999;
  6. int next[4][2]={
  7. {0,1},{1,0},{0,-1},{-1,0}};
  8. void dfs(int tx,int ty,int step)
  9. {
  10. if(tx==p&&ty==q){
  11. if(step<minn)minn=step;
  12. return ;
  13. }
  14. for(int i=0;i<4;i++){
  15. int x,y;
  16. x=tx+next[i][0];
  17. y=ty+next[i][1];
  18. if(x<1||y<1||x>n||y>m)continue;
  19. if(a[x][y]==0&&v[x][y]==0){
  20. v[x][y]=1;
  21. dfs(x,y,step+1);
  22. v[x][y]=0;
  23. }
  24. }
  25. }
  26. int main()
  27. {
  28. cin>>n>>m;
  29. for(int i=0;i<n;i++)
  30. for(int j=0;j<m;j++)
  31. cin>>a[i][j];
  32. cin>>p>>q;
  33. v[1][1]=1;
  34. dfs(1,1,0);
  35. cout<<minn;
  36. return 0;
  37. }

下面是广搜的解法:

  1. 广度优先搜索解救小哈
  2. 众所周知:深搜用栈广搜用队列。
  3. #include<cstdio>
  4. #include<cmath>
  5. #include<iostream>
  6. #include<cstdlib>
  7. using namespace std;
  8. int a[51][51]={},n,m,v[51][51]={},p,q;//迷宫,状态数组,初始化
  9. struct que{
  10. int x;
  11. int y;
  12. int step;
  13. }queue[2505];//手写队列
  14. int main()
  15. {
  16. int head=1,tail=2,x,y;
  17. cin>>m>>n;
  18. for(int i=1;i<=n;i++)
  19. for(int j=0;j<=m;j++)
  20. cin>>a[i][j];//输入迷宫,障碍物输入1,其他为0;
  21. a[1][1]=1;
  22. v[1][1]=1;
  23. queue[1].x=1;
  24. queue[1].y=1;
  25. queue[1].step=0;//第一个入队
  26. int next[4][2]={
  27. {0,1},{1,0},{0,-1},{-1,0}};//能够遍力四个方面
  28. bool flag=false;
  29. while(head<tail)
  30. {
  31. for(int i=0;i<4;i++){
  32. x=queue[head].x+next[i][0];
  33. y=queue[head].y+next[i][1];
  34. if(x<1||y<1||x>n||y>m)continue;//判断是否越界
  35. if((a[x][y]==0)&&(v[x][y]==0)){//判断是否可行
  36. v[x][y]=1; //标记
  37. queue[tail].x=x;
  38. queue[tail].y=y;
  39. queue[tail].step=queue[head].step+1;
  40. tail++;//队尾加1
  41. }
  42. if(x==p&&y==q){
  43. flag=true;
  44. break;
  45. }//得到结果
  46. }
  47. if(flag)break;//退出循环
  48. head++;//该点已经遍历完毕,出队
  49. }
  50. cout<<queue[--tail].step;//打印!
  51. return 0;
  52. }

发表评论

表情:
评论列表 (有 0 条评论,365人围观)

还没有评论,来说两句吧...

相关阅读

    相关 广

    一、深搜 属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次;

    相关 广(初学者)

    搜索入门     最近对搜索有了一点浅显的了解,想跟大家分享分享。     说起来我也是初学者,恰巧有些自己的理解,想起来自己开始学习搜索的情况,真是一把鼻子一把

    相关 DFS\广BFS 初步入门

    首先,不管是BFS还是DFS,由于时间和空间的局限性,它们只能解决数据量比较小的问题。 深搜,顾名思义,它从某个状态开始,不断的转移状态,直到无法转移,然后退回到上一步的状态