• 洛谷P1238 走迷宫


    题目描述

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

    优先顺序:左上右下

    输入格式

    第一行是两个数m,n(1<m,n<15),接下来是m行n列由1和0组成的数据,最后两行是起始点和结束点。

    输出格式

    所有可行的路径,描述一个点时用(x,y)的形式,除开始点外,其他的都要用“一>”表示方向。

    如果没有一条可行的路则输出-1。

    输入输出样例

    输入 #1
    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
    输出 #1
    (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)


    思路:就是一个深搜,不过要记录前面从哪里走来的,那么只需要开一个pre数组来记录前面的坐标即可。pre[i][j][0]记录点(i,j)前一个点的横坐标,pre[i][j][1]则记录纵坐标。

    代码:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int m,n,sx,sy,lx,ly,f;
    int dy[5]={0,-1,0,1,0};//这里是最细节的地方,因为在这种行列的矩阵里,经常会出现或者是大部分都是x表示纵坐标而y表示横坐标,但是我忽略了这一点,由于这个题要求优先级了,所以顺序不对是不行的。经过大佬fys的指点,我才成功地A了这个题,所以这个时候就要把x和y的数组换一下,左边就是y-1,而下边则是x+1,这里又是一个细节,因为左上角的点是(1,1),所以往下走其实纵坐标(x)要+1,往上走则要-1
    int dx[5]={0,0,-1,0,1};
    int a[20][20];
    int pre[20][20][2];
    void print(int x0,int y0)
    {
        if(pre[x0][y0][0]!=sx||pre[x0][y0][1]!=sy)//由于第一个起点也要输出但是前面没有箭头,所以要特别输出,不能在这个函数里,所以第二个点的时候就停止 print(pre[x0][y0][0],pre[x0][y0][1]);//如果它前面还有点的话,那么继续递归。一定要先递归再输出,这样才能从第一个点从前往后输出
        cout<<"-"<<">"<<"("<<x0<<","<<y0<<")";//print函数用来输出结果
    }
    void dfs(int x1,int y1)
    {
        if(x1==lx&&y1==ly)
        {
            f=1;//f用来判断有没有路径到达终点,如果没有输出-1
            cout<<"("<<sx<<","<<sy<<")";//如果找到了这个点,那么输出并且特别输出起点
            print(lx,ly);
            cout<<endl;//输出回车别忘了
            return;
        }
        a[x1][y1]=0;
        for(int i=1;i<=4;i++)
        {
            int x=x1+dx[i];
            int y=y1+dy[i];
            if(a[x][y]==1&&x>=1&&x<=n&&y>=1&&y<=m)
            {
                a[x][y]=0;
                pre[x][y][0]=x1;
                pre[x][y][1]=y1;
                dfs(x,y);
                a[x][y]=1;//这就是当初我死活都学不会的回溯,每次递归完之后你要把它恢复原状,以便下一次搜索时还是初始状态
                pre[x][y][0]=0;
                pre[x][y][1]=0;
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>a[i][j];
        cin>>sx>>sy>>lx>>ly;
        if(a[sx][sy]==0||a[lx][ly]==0)
        {
            cout<<-1<<endl;
            return 0;
        }
        dfs(sx,sy);//搜索
        if(f==0)//如果没有到达终点,那么输出-1
            cout<<-1<<endl;
        return 0;
    }
  • 相关阅读:
    git
    浏览器喧嚷过程
    B/S架构与C/S架构
    simpleDateFormat
    oracle中case when的用法
    Java程序利用Jdbc连接数据库
    List 和 Set与Map
    队列和栈
    toString方法分析
    java中的构造器
  • 原文地址:https://www.cnblogs.com/57xmz/p/13038960.html
Copyright © 2020-2023  润新知