深度优先搜索(迷宫问题)

本文介绍了如何使用深度优先搜索(DFS)算法解决二维迷宫问题,从给定的起点找到目标位置的最短路径,避开障碍物。通过递归和书签数组记录已访问节点,实现路径优化。
摘要由CSDN通过智能技术生成
经典例子——解救小哈(深度搜索)

【题目描述】

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

迷宫由n行m列的单元格组成(n和m都小于等于50),每个单元格要么是空地(用0表示),要么是障碍物(用1表示)。你的任务是帮助小哼找到一条从迷宫的起点(x,y)通往小哈所在位置(q,p)的最短路径。注意障碍物是不能走的,当然小哼也不能走到迷宫之外。

【输入】

首先输入n和m,代表二维数组(迷宫)的行和列。

接着输入一个二维数组。

最后输入迷宫的起点坐标(x,y)和小哈所在的位置(q,p)。

【输出】

小哼从起点通往小哈位置的最短路径。

样例输入

5 4

1 1 2 1

1 1 1 1

1 1 2 1

1 2 1 1

1 1 1 2

1 1 4 3

样例输出 

7

上面这个题就是简单的用深度优先搜索来解决的迷宫问题,就是下面这个代码的进阶版,即二维数组的版本,只要了解下面代码原理,就可以由点及面,解决这个简单的走迷宫问题。

 

#include <stdio.h>
int a[10],book[10],n;
void dfs(int step)      //step表示站在第几个盒子前面
{
    int i;
    if(step==n+1)       //如果站在第n+1个盒子面前,则表示前n个盒子已经放好扑克牌了
    {
        //输出一种排序(1~n号盒子的扑克牌编号)
        for(i=1;i<=n;i++)
        {
            printf("%d",a[i]);
        }
        printf("\n");
        return ;     //返回之前的一步(最近一次调用dfs函数的地方)
    }
    for(i=1;i<=n;i++)
    {
        if(book[i]==0)
        {
             a[step]=i ;  //将i号扑克牌放入第step个盒子中
             book[i]=1; //将book[i]设为1,表示i号扑克牌已经不在手
             dfs(step+1);   //这里通过函数的递归调用来实现
             book[i]=0;     //将刚才尝试的扑克牌收回,才能进行下一次尝试
        }
       
    }
}
int main()
{
    scanf("%d",&n);     //输入n为1~9的整数
    dfs(1);             //首先站到1号盒子面前
    getchar();
    return 0;
}

 迷宫问题基本原理代码

#include <stdio.h>
int min=999;
int p,q;                //终点位置
int step;
int a[100][100],book[100][100]; //1表示空地,2表示障碍物
void dfs(int x,int y,int step)
{
    if(x==p&&y==q)
    {
         if(step<min)
        {
        min=step;
        return;
        }
    }
   if(a[x][y+1]==1&&book[x][y+1]==0)
   {
        book[x][y+1]=1;
        dfs(x,y+1,step+1);
        book[x][y+1]=0;
   }
   if(a[x+1][y]==1&&book[x+1][y]==0)
   {
        book[x+1][y]=1;
        dfs(x+1,y,step+1);
        book[x+1][y]=0;
   }
   if(a[x][y-1]==1&&book[x][y-1]==0)
   {
        book[x][y-1]=1;
        dfs(x,y-1,step+1);
        book[x][y-1]=0;
   }
   if(a[x-1][y]==1&&book[x-1][y]==0)
   {
        book[x-1][y]=1;
        dfs(x-1,y,step+1);
        book[x-1][y]=0;
   }
}
int main()
{
    int start_x,start_y;
    int m,n;
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    scanf("%d",&a[i][j]);       //输入迷宫数字图形

    scanf("%d%d%d%d",&start_x,&start_y,&p,&q);
    dfs(start_x,start_y,0);
    printf("%d",min);
}

这个代码dfs函数跟上面代码类似,就是由判断一个方向,转变为判断四个方向。代码设初始位置为x,y。右:(x,y+1),下:(x+1,y),左:(x,y-1),上:(x-1,y),当然也可以设成其他形式,主要看理解。同第一个代码一样,需要设一个book[]数组来判断是否走过,如果没走过并且不是死路,就可以进入,然后再if中再次调用dfs函数去走下一步,这就用到嵌套了,这是一步很巧妙的写法,如果到达了终点也可以通过这一层层的嵌套进行回溯,这也是为什么dfs函数后面将book又变成0,即未走过了。而再判断走的方向一般是按顺时针来的。

迷宫问题代码优化

下面代码是用循环将上面方向代码整合了。

#include <stdio.h>
int min=999;
int p,q;                //终点位置
int step;
int a[100][100],book[100][100]; //1表示空地,2表示障碍物
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void dfs(int x,int y,int step)
{
    if(x==p&&y==q)
    {
         if(step<min)
        {
        min=step;
        return;
        }
    }
  for(int k=0;k<=3;k++)
  {
    int tx,ty;
     tx=x+dx[k];
     ty=y+dy[k];
    if(a[tx][ty]==1&&book[tx][ty]==0)
    {
        book[tx][ty]=1;
        dfs(tx,ty,step+1);
        book[tx][ty]=0;
    }
  }
}
int main()
{
    int start_x,start_y;
    int m,n;
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    scanf("%d",&a[i][j]);       //输入迷宫数字图形

    scanf("%d%d%d%d",&start_x,&start_y,&p,&q);
    dfs(start_x,start_y,0);
    printf("%d",min);
}

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值