迷宫问题----深搜经典问题

迷宫问题是深搜算法的最常见也是最基础的题型之一

深搜大家应该都已经理解了
如果还不知道深搜是什么可以参考我之前的一篇:深搜讲解
我们把我们撞南墙才回头的思想运用到我们的迷宫问题中
就可以理解为:

从起点开始随便找一条路开始走
走到了终点或没有继续向前的格子就回头

用最简单的2x2迷宫来举例

如果我们设起点是(1,1)这个点,终点是(2,2)这个点,
障碍物是(2,1)这个点。

我们从起点开始可以选择去(1,2)或者去(2,1),但后者是障碍物,所以我们只能选择(1,2),到了这个点我们可以只能去(2,2)(因为走过的地方不能再走),所以我们到达了终点,此时我们回头去寻找另外的路径。但我们发现,不管退到前面的哪一步(包括退回到起点),我们都没有其他的路径选择,所以最后的答案就只有一条。
(如果没有理解,建议先把上一篇讲解深搜的先理解透彻)。
接下来我们直接看code
点击查看题目>>来自洛谷

方向数组代码

#include <bits/stdc++.h>

using namespace std;
int a[10][10];
int fxx[5]={0,0,0,1,-1};
int fxy[5]={0,1,-1,0,0};
int n,m,t;
int toi,toj;
int flag=0;
void dfs(int nowi,int nowj);
int main()
{
    cin >> n >> m >> t;
    for(int i=0;i<=n+1;i++)
    {
        for(int j=0;j<=m+1;j++)
        {
            if(i==0||j==0||j==n+1||i==n+1)
            {
                a[i][j]=1;
            }
        }
    }
    int nowi,nowj;
    cin >> nowi >> nowj >> toi >> toj;
    a[nowi][nowj]=1;
    int xi,xj;
    while(t--)
    {
        cin >> xi >> xj;
        a[xi][xj]=1;
    }
    dfs(nowi,nowj);
    cout << flag << endl ;
    return 0;
}
void dfs(int nowi,int nowj)
{
    if(nowi==toi&&nowj==toj)
    {
        flag++;
        return ;
    }
    for(int i=1;i<=4;i++)
    {
        if(a[nowi+fxx[i]][nowj+fxy[i]]==0)
        {
            a[nowi+fxx[i]][nowj+fxy[i]]=1;
            dfs(nowi+fxx[i],nowj+fxy[i]);
            a[nowi+fxx[i]][nowj+fxy[i]]=0;
        }
    }
}

普通代码

#include <bits/stdc++.h>

using namespace std;
int n,m,t;
int a[10][10]; //标记x,y这个点是否是障碍物或已经被走过
int nowi,nowj;//现在走到哪里了,即现在的坐标
int toi,toj;//终点坐标
int flag;//有几种路径,即最后输出的答案
void work(int x);//运行函数
int main()
{
    while(cin >> n >>m >> t)
    {
        flag=0;
        cin >> nowi >> nowj >> toi >> toj;
        a[nowi][nowj]=1;//对起点进行标记
        for(int i=1; i<=t; i++)
        {
            int x,y;
            cin >> x >> y;
            a[x][y]=1;//给障碍物进行标记
        }
        work(1);
        cout << flag << endl ;
        a[nowi][nowj]=0;//清楚此次起点的标记
        memset(a,0,sizeof(a));//最后清0数组,具体是清楚障碍物标记的地方
    }
    return 0;
}
void work(int x)
{
    if(nowi==toi&&nowj==toj)
    //达到了终点,flag++,并且不再进行函数的其他操作,其实可以++完直接return
    {
        flag++;
    }
    else
    {//这里的x为1,2,3,4的操作可以根据自己喜好来调换
        if(x==1)//把它移动向行数增加的那一格
        {
            if(a[nowi+1][nowj]==0&&nowi+1<=n)
            {
                a[nowi+1][nowj]=1;//标记这个位置
                nowi++;
                work(1);
                nowi--;
                a[nowi+1][nowj]=0;//别忘记这里要清楚标记
            }//如果不懂这种if函数为什么这样写,可以先理解上一篇的代码,有详细讲解
        }
        if(x==2)//把它移动向列数增加的那一格
        {
            if(a[nowi][nowj+1]==0&&nowj+1<=m)
            {
                a[nowi][nowj+1]=1;
                nowj++;
                work(1);
                nowj--;
                a[nowi][nowj+1]=0;
            }
        }
        if(x==3)//把它移动向行数减少的那一格
        {
            if(a[nowi-1][nowj]==0&&nowi-1>=1)
            {
                a[nowi-1][nowj]=1;
                nowi--;
                work(1);
                nowi++;
                a[nowi-1][nowj]=0;
            }
        }
        if(x==4)//把它移动向列数减少的那一格
        {
            if(a[nowi][nowj-1]==0&&nowj-1>=1)
            {
                a[nowi][nowj-1]=1;
                nowj--;
                work(1);
                nowj++;
                a[nowi][nowj-1]=0;
            }
        }
        if(x+1<=4)//不能加else哦,理解一下
        /*不管是不满足以上条件,还是从上面条件运行完再出来,
        都要进行它的下一项(如果没有超出边界的话)*/
            work(x+1);
    }
}

发布了44 篇原创文章 · 获赞 13 · 访问量 2351

猜你喜欢

转载自blog.csdn.net/NEFU_kadia/article/details/104126435
今日推荐