scau 18714 迷宫问题

 

这道题用到了递归思想,递归这种东西挺抽象的,还是那句话,切忌头脑编译,选个简单例子在纸上画一下,整道题的逻辑就会清晰很多。这道题老师上课有讲,也在电脑上打过代码,当时听的一知半解,又不爱动手算,这道题搁置了差不多两个星期我才着手写。

下面是我的解析。

1、首先,定义两个全局数组变量a[4]={1,-1,0,0}和b[4]={0,0,1,-1},这两个数组是用来控制方向的

for(int i=0;i<3;i++)
    {
        int nx=x+a[i];
        int ny=y+b[i];
        if(c[nx][ny]!='1')//没走过或者不是墙
        {
            c[nx][ny]='1';//走过的地方标记为1,避免死循环
            dfs(nx,ny);
        }
    }

当i=0时,a[0]=1,b[0]=0,那么nx=x+a[i],ny=y+b[i],相当于往下走了一步;当i=1时,a[1]=-1,b[1]=0,相当于往上走了一步;当i=2时,a[2]=0,b[2]=1,相当于往右走了一步;当i=3时,a[3]=0,b[3]=-1,相当于往左走了一步

2、在上面的代码段中,有 if(c[nx][ny]!='1')//没走过或者不是墙
                                          {
                                               c[nx][ny]='1'; //走过的地方标记为1,避免死循环
                                               dfs(nx,ny); //以新走到的格子为中心调用函数
                                          }

当c[nx][ny]!='1'时,即c[nx][ny]==0,说明这个格子可以走,并且没有走过,那么就往这个格子走一步,同时赋值1,再调用函数dfs(nx,ny),即以这个格子为中心,往它的上下左右试探方向。当它的上方或下方或左方或右方格子的值为1时,就一直进行for循环,直到找到一个不为1的格子为之,这样才能继续往下走。那如果这个格子的上下左右都为1,那说明走到了一条“死路”,此时递归就会回到上一个格子,以上一个格子为中心,再次搜索上下左右。

下面以3*3的迷宫为例进行解释。

3 3

0 1 0

0 1 1

0 0 0

1、先以c[1][1]为中心搜索,for循环第一次有nx=2,ny=1,即往下走,发现c[2][1]==0,没有走过,那我就把c[2][1]标记为1,接着调用函数,以c[2][1]为中心进行搜索

2、此时c[2][1]为中心,第一次循环有nx=3,ny=1,即往下走,发现c[3][1]==0,也没有走过,把c[3][1]标记为1,调用函数,以c[3][1]为中心进行搜索

3、此时c[3][1]为中心,第一次循环有nx=4,ny=1,即往下走,发现走到了墙走不了了,第二次循环有nx=2,ny=1,即往上走,也走过了,进行第三次循环,有nx=3,ny=2,即往右走,c[3][2]==0,没有走过,那就往c[3][2]走,并把它标记为1,再调用函数,以c[3][2]为中心进行搜索

4、此时c[3][2]为中心,同理,循环到第三次,往右走,走到c[3][3],此时dfs(3,3),满足了递归结束条件(x==n && y==m)即走到了迷宫出口

下面是全部代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n,m,ok=0;
char c[105][105]={' '};
int a[4]={1,-1,0,0};
int b[4]={0,0,1,-1};//每次递归判断四个方向(上下左右)是否可以走
        //下上右左
void dfs(int x,int y)//dfs——深度优先算法
{
    if(x==n && y==m)//出口坐标为(n,m) //递归结束条件放在前面
    {
        ok=1;//走到出口
        return ;
    }
    for(int i=0;i<3;i++)
    {
        int nx=x+a[i];//试探方向
        int ny=y+b[i];
        if(c[nx][ny]!='1')//该点没走过或者该点不是墙
        {
            c[nx][ny]='1';//走过的地方标记为1,避免死循环
            dfs(nx,ny);//以这个刚走到的点为中心递归进行搜索
        }
    }
}
int main()
{
    int i,j;
    cin >> n >> m;//n行m列
    for(i=0;i<105;i++)
    {
        for(j=0;j<105;j++)
        {
            c[i][j]='1';//全部标为'1','1'表示不可走
        }
    }
    for(i=1;i<=n;i++)//n行m列外的周围相当于围墙
    {
        for(j=1;j<=m;j++)
        {
            cin >> c[i][j];//输入圈内的数据
        }
    }
    dfs(1,1);//从入口开始调用函数
    if(ok==1)
        cout<< "yes";
    else
        cout<< "no";
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值