数据结构-回溯法求解简单迷宫

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”

在生活中,也会出现回溯方法的运用,比如我们有些没有反向感的朋友们,去西安玩耍,走到钟楼底下环形通道迷路了,想要找到7出口,又不知道其他路径可行的情况下,就会原路返回到原点,继续探索可行的路径,知道找到出口位置。这就是回溯法在生活中的例子,

在数据结构中,也也会用到回溯法 ,比如在解决迷宫问题上,回溯法就粉墨登场了,

在迷宫中,从入口点进去,寻找出口,就像我们在钟楼环形通道寻找7出口一样,当眼前有几条路径可以走时,就会开始探测着走,如果是出口,就走出迷宫,如果不是出口,就回退到刚才的位置,继续探测,直到找到出口。

下面是具体代码的实现(该迷宫不带环,且只有一条通路)

这里写图片描述

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "maze.h"

//初始化迷宫地图
void MazeInit(Maze* m,int map[COL][ROW])
{
       //迷宫为空,直接返回
      if(m==NULL)
      {
            return ;
      }

      size_t i=0;
      //初始化迷宫
      for(  ;i<COL;i++)
      {
            size_t j=0;
            for(  ;j<ROW;j++)
            {
                  m->_map[i][j]=map[i][j];


            }
      }
      return ;


}
//迷宫打印
void MazePrint(Maze *m,int map[COL][ROW])
{
      if(  m==NULL)
      {
            return ;
      }
      size_t i=0;
      //开始打印迷宫
      for(  ;i<COL;i++)
      {
            size_t j=0;
            for(  ;j<ROW;j++)
            {
                  printf(" %2d",m->_map[i][j]);

            }
            //一行打印完毕,准备换行
            printf("\n");
      }
      printf("\n");
      return ;

}
//开始走迷宫
void GetPath(  Maze* m,Point entry) 
{

    if(  m==NULL)  
    {
        return;
    } 
    //利用此函数帮我们完成递归 
    _GetPath(  m,entry,entry);
}      

走迷宫基础框架

//利用该函数完成递归
void _GetPath(Maze* m,Point cur,Point entry)
{

     //1.判断当前点能否能落脚
      if(!CanStay(m,cur))  
      {

         return;
      } 

      printf("cur:(%d,%d)\n",cur.x,cur.y);

      //2.若能落脚,给当前位置坐标记为2
     Mark(m,cur);
     //3.若当前点为出口,说明找到了一条出路,探测就结束
     if(Exit(m,cur,entry))  
     {

        printf("找到了一条出路\n");
        return;
    }  
     //4。若当前点不是出口,按顺时针顺序探测四个方向的相邻点

     //向上探测(纵坐标不变,横坐标减1)
     Point up=cur;
     up.x-=1;
     _GetPath(  m,up,entry);
     //向右探测(横坐标不变,纵坐标加1)
     Point right=cur;
     right.y+=1;
     _GetPath(  m,right,entry);
     //向下探测(纵坐标不变,横坐标加1)
     Point down=cur;
     down.x+=1;
     _GetPath(  m,down,entry);
     //向左探测(横坐标不变,纵坐标减1)
     Point left=cur;
     left.y-=1;
     _GetPath(  m,left,entry);
} 

下面是每个函数的具体实现


//判断该点是否是出口
int Exit(Maze* m,Point cur,Point entry)
{

    //当前点是入口,不是出口,返回0
    if(cur.x==entry.x&&cur.y==entry.y)
    {
          return 0;
    }
    //如果该点在边界上,且不是入口,则一定是出口,返回1
    if(cur.x==0||cur.y==0||cur.x==COL-1||cur.y==ROW-1)
    {
          return 1;
    }
    return 0;


}
//标记当前点为2
void Mark( Maze* m,Point cur)
{
    if(  m==NULL)
    {
          return ;
    }
    m->_map[cur.x][cur.y]=2;

}
//判断当前点是否可以落脚
int CanStay( Maze* m,Point cur)
{
      //该点在地图外,返回0
      if(cur.x<0||cur.x>=COL||cur.y<0||cur.y>=ROW)
      {
            return 0;
      }
      //该点在地图内
      //是1就可以落脚,返回1,2,0均不可以落脚
      int value=m->_map[cur.x][cur.y];
      if(  value==1)
      {
            return 1;
      }

      //2,0均不可以落脚,返回0
      return 0;
}



测试代码



#include <stdio.h>
#include "maze.h"
#define TESTLINE printf("\n=========%s=========\n ",__FUNCTION__);
void TestInit(  )  
{

    TESTLINE;

    int map[COL][ROW]={
          {0,1,0,0,0,0},
          {0,1,1,1,0,0},
          {0,1,0,1,0,0},
          {1,1,0,1,1,0},
          {0,0,0,0,0,0}
    };
    Maze maze;
    MazeInit(&maze,map);
    MazePrint(&maze,map);
    Point entry;
    entry.x=0;
    entry.y=1;
    GetPath(&maze,entry);

}  
int main(  )
{

      TestInit(  );
      return 0;
}

这里写图片描述

将走过的路径打印出来
这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值