走迷宫(DFS)

题面(from luogu)
走迷宫
有一个m*n格的迷宫(表示有m行、n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,文件读入这mn个数据和起始点、结束点(起始点和结束点都是用两个数据来描述的,分别表示这个点的行号和列号)。现在要你编程找出所有可行的道路,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出相应信息(用-l表示无路)。
优先顺序:左上右下

输入格式:
第一行是两个数 m,n(1<m,n<15),接下来是m行n列由1和0组成的数据,最后两行是起始点和结束点。
输出格式:
所有可行的路径,描述一个点时用(x,y)的形式,除开始点外,其他的都要用“一>”表示方向。
如果没有一条可行的路则输出-1。
样例.in
5 6
1 0 0 1 0 1
1 1 1 1 1 1
0 0 1 1 1 0
1 1 1 1 1 0
1 1 1 0 1 1
1 1
5 6
样例.out
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)

题目分析
感觉就是这一题:https://www.luogu.org/problemnew/show/P1605 的翻版(不知道为什么难度会上升。。。)
具体的可见这个:https://blog.csdn.net/c_uizrp_dzjopkl/article/details/81813542

大体上面是一样的,但是,有一点是需要注意的:优先顺序:左上右下
我被坑到了。。。。。。。。

代码

#include <bits/stdc++.h>
using namespace std;

int dx[5]={0,0,-1,0,1};        //介值(注意:有优先级的!)
int dy[5]={0,-1,0,1,0};
int a[20][20],ans[10000][3],vis[20][20],n,m,a1,a2,b1,b2,k=1,total=0;   
 //a是同map数组,ans存的是答案,vis判断那些点去过,k是当前答案长度,total用来判断有没有答案  

void write(int c)           //自己写的输出函数
{
//  cout<<'(',a1<<','<<a2')'<<"->";
    for (int i = 1; i <= c; i++)
        cout<<'('<<ans[i][1]<<','<<ans[i][2]<<")->";
    cout<<'('<<b1<<','<<b2<<')'<<endl;

    total++;             //方案数++
}

void search(int x,int y)        //x,y是当前的位置
{
    if (x == b1 && y == b2)      //找到目标点了
        {
            write(k-1);      //从k-1个开始输出
            return;          //回溯
        } 
        else             //没找到就继续找
            {
                for (int i = 1; i <= 4; i++)          //四个方向开始搜
                    if (a[x+dx[i]][y+dy[i]] == 0 || vis[x+dx[i]][y+dy[i]] == 1) continue;   //要跳过的条件
                        else       //反之就是可以走
                            {
                                ans[k][1] = x;      //记录x轴答案
                                ans[k][2] = y;      //y轴答案
                                k++;                //答案的长度+1;
                                vis[x+dx[i]][y+dy[i]] = 1;     //打标记
                                search(x+dx[i],y+dy[i]);       //向前搜
                                vis[x+dx[i]][y+dy[i]] = 0;     //回溯
                                k--;
                            }
            }
}

int main()
{
    memset(a,0,sizeof(a));        //初始化
    memset(vis,0,sizeof(vis));       //所有的点都没有走过

    cin>>n>>m;                       //输入
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin>>a[i][j];
    cin>>a1>>a2;       //起点
    cin>>b1>>b2;       //终点

    vis[a1][a2] = 1;    //起点永远要标记!!!

    search(a1,a2);      //从给出的点开始搜

    if (total == 0) cout<<-1;     //无解情况的输出

    return 0;      //完美的结束程序
}
                                   **蒟蒻新星c_uizrp_dzjopkl原创**

猜你喜欢

转载自blog.csdn.net/c_uizrp_dzjopkl/article/details/82287505