秒懂算法 | 回溯算法

举报
TiAmoZhang 发表于 2023/03/06 13:37:26 2023/03/06
【摘要】 回溯算法

微信图片_20230306133346.jpg

例题:已知一个迷宫以及迷宫的入口和出口,现在从迷宫的入口出发,看是否存在一条路径?如果存在,则输出YES,不存在,输出NO。

解析:计算机走迷宫时,利用“试探和回溯”的方法,即从入口出发,顺某一方向向前探索,若能走通,则继续往前走;否则沿原路退回,换一个方向再继续探索,直至所有可能的通路都探索到为止,如果所有可能的通路都试探过,还是不能走到终点,那就说明该迷宫不存在从起点到终点的通道。

下图为例,介绍一下迷宫的具体走法。下图中灰色部分墙体部分:

640.jpg

1)从入口进入迷宫之后,理论上有前后上下四个方向可以走,这里以前、下、后、上四个方向为顺序进行迷宫的道路搜索。如果有路,则向前,无路则按顺序向下一个方向进行搜索。图a是顺着向前方向一直搜索,当向前方向不通时,则向下如图b搜索,还不通,则向后搜索,后面已经搜索过了(需要一个标志位,搜索过的标志为不通),则继续向上搜索如图d所示,发现仍然不通(这里需要对边界进行判断,对于超过边界的区域认为不通)。


总结:迷宫中一共有三种类型的路不通

  • 前方道路是墙体

已经访问过的路径
超出迷宫边界
(2)此时,搜索位置的四个方向都走不通,就需要退回到前一个位置,这叫回溯。当回到上一个位置后,由于原来是向前搜索的,结果不通,则此时需要换一个方向搜索,现在向下搜索,此时是通路。在下一个位置上,继续按照前、下、后、上顺序继续搜索,如图e所示。

(3)在图e的搜索位置上,向前不通,转向向下搜索,有路可通,则下移一格,如图f所示。

(4)继续向前搜索,有通路,如图g所示。

(5)发现向前搜索,无路,转向向下搜索,下移一格,到达出口。如图h所示。

对于迷宫的数据表示方法,一般都是采用二维数组表示。至于数据类型,可以采用整型或者字符型表示,本题为了方便,采用了字符型。

string map[5]={"0000#",
             "0#0##",
         "#00##",
         "#0#00",
         "#0000"};

二维数组中,字符'0'表示通路,'#'表示墙体。

在迷宫中,相对中心点,向四个方向搜索的数据表示可以用图1表示。

640.jpg

这里利用两个数组dx和dy分别表示数据偏移量。


int dx[4]={1,0,-1,0};
int dy[4]={0,-1,0,1};

对这两个数组的顺序访问,就相当于分别向前、下、后、上进行搜索。

int dx[4]={1,0,-1,0};
int dy[4]={0,-1,0,1};
对这两个数组的顺序访问,就相当于分别向前、下、后、上进行搜索。
int x,y,x1,y1,nx,ny,n;
bool visited[100][100],flag=false;
int dfs(int x, int y)
{
  if(x==x1 && y==y1)//到达
  {
    cout<<"YES"<<endl;
    flag=true;
    return 1;
  }
  for(int i=0;i<4;++i)
  {
    nx=x+dx[i];//搜索四个方向
    ny=y+dy[i];
    if(nx<0 || nx>=n || ny<0 || ny>=n)//判断是否越界以及是否走过
      continue;
    if(!visited[nx][ny])
    {
      visited[nx][ny]=true;//走过
      dfs(nx,ny);//否则从现在的点开始继续往下搜索
      visited[nx][ny]=false;//重新标记未走过
    }
  }
  return 0;
}

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。