【题解】(LGJ原创)蝴蝶旅客

题目描述

歌姬什么的,不干了啦!星尘要旅游!

于是星尘换上了蝴蝶套装在一片为 (p) 层每层n行m列的矩阵中开始了她的旅行,她从 ((1,1,1)) 出发,到 ((x,y,z)) 去。这片空间里有一些是不能通过的,因为这些空间内没有以太之尘,星尘飞不起来。现在告诉你哪里有以太之尘,请你依照 (x) 轴正 ((x+1))(y) 轴正 ((y+1))(z) 轴正 ((z+1))(x) 轴负 ((x-1))(y) 轴负 ((y-1))(z) 轴负 ((z-1))的顺序找到到达终点的所有路径,

对于每一条路径,不能走回头路,因为走过的路也没有以太之尘。记住,每条路径之间不会互相干扰,这一条走过某个位置不影响另一条路径走过这个位置。如果不能到达输出 (-1)

输入格式

第一行六个整数表示 (p) 层每层 (n)(m) 列和终点坐标 (x、y、z)
接下来有 (p) 个矩阵,每个矩阵有 (n)(m) 列,(1) 表示可以通过。

输出格式

输出从起点到终点的所有路径,不存在输出 (-1)

样例输入

3 3 3 3 3 1

1 1 1
0 0 1
0 0 1

1 0 0
0 0 0
0 0 1

1 1 1
0 0 1
0 0 1

样例输出

(1,1,1)->(1,2,1)->(1,3,1)->(2,3,1)->(3,3,1)
(1,1,1)->(1,1,2)->(1,1,3)->(1,2,3)->(1,3,3)->(2,3,3)->(3,3,3)->(3,3,2)->(3,3,1)

数据范围

(n,m,ple 10)

题目大意

LGJ出的毒瘤搜索……但是这个……三维搜索……有(yi)点复杂啊……

分析

如果要输出路径的话就必须用深搜勒~ 但是,“在写这道题被 (TLE) 狂虐中我明白了,越是优化剪枝(其实并没有什么可剪的)抓耳挠腮,越会发现 (dfs) 的力量是有限的,除非超越 (dfs)。……所以……我用 (bfs) 辣!JOJO![哔——]”

注意到如果根本无法到达终点的话,(dfs) 就会像无头苍蝇一样到处搜索,时间复杂度大大提高,所以,可以考虑先用 (bfs) 搜索一遍判断是否可以到达终点,如果不能直接输出 (-1) 结束程序,这样便使得 (dfs) 不会因为无法到达终点而时间超限。

确定算法之后就来到了这道题最另人头秃的地方了:确定 (x、y、z)
将样例画出来之后如下图所示:
(黑色、蓝色、红色分别为不同的层)

题目中的两条路径分别为:

所以,题目中的坐标 ((x,y,z)) 指的是第 (x)(y)(z) 列的点,在搜索或输入时一定要注意!

Code

#include <bits/stdc++.h>
using namespace std;
int a[11][11][11],v[11][11][11];
struct node{
    int x,y,z;
}d[1010];//bfs的队列 
int dx[6]={1,0,0,-1,0,0},dy[6]={0,1,0,0,-1,0},dz[6]={0,0,1,0,0,-1};//坐标移动数组 
int px[1010],py[1010],pz[1010];//输出(put_out)数组 
int m,n,p,zx,zy,zz;
bool bfs()//判断是否能够到达终点 
{
    int head=1,tail=2;
    while(head<=tail){
        if(d[head].x==zx&&d[head].y==zy&&d[head].z==zz)
            return true;
        for(int i=0;i<=5;i++){
            int tx=d[head].x+dx[i],ty=d[head].y+dy[i],tz=d[head].z+dz[i];
            if(!v[tz][tx][ty]&&a[tz][tx][ty]){//【注意】在这里我的坐标是(z,x,y)! 
                v[tz][tx][ty]=1;//第z层的第x行第y列的点 
                d[tail].x=tx;
                d[tail].y=ty;
                d[tail].z=tz;
                tail++;
            }
        }
        head++;
    }
    return false;
}
void put_out(int x)
{
    for(int i=0;i<x;i++)
        printf("(%d,%d,%d)->",px[i],py[i],pz[i]);
    printf("(%d,%d,%d)
",px[x],py[x],pz[x]);
    return;
}
void dfs(int x,int y,int z,int cnt)
{
    if(x<1||y<1||z<1||x>n||y>m||z>p) return;//这里x、y、z对应的n、m、p和输入时的顺序有所不同
    if(x==zx&&y==zy&&z==zz){//x指层数,y、z才是横纵坐标哦
        put_out(cnt);
        return;
    }
    for(int i=0;i<6;i++){
        int tx=x+dx[i],ty=y+dy[i],tz=z+dz[i];
        if(a[tz][tx][ty]){
            a[tz][tx][ty]=0;
            cnt++;
            px[cnt]=tx;
            py[cnt]=ty;
            pz[cnt]=tz;
            dfs(tx,ty,tz,cnt);
            cnt--;
            a[tz][tx][ty]=1;
        }
    }
}
int main()
{
    scanf("%d%d%d%d%d%d",&p,&n,&m,&zx,&zy,&zz);
    for(int i=1;i<=p;i++)//【注意!】a(i,j,k)在这里记录的是第i层j行k列的点 
        for(int j=1;j<=n;j++)//如果在这里的输入改为a[j][k][i],上面的搜索中就可以用x,y,z了 
            for(int k=1;k<=m;k++)
                scanf("%d",&a[i][j][k]);
    d[1].x=d[1].y=d[1].z=1;
    memset(v,0,sizeof(0));
    v[1][1][1]=0;
    if(!bfs()){//如果不能到达直接输出-1 
        printf("-1");
        return 0;
    }
    px[0]=py[0]=pz[0]=1;
    a[1][1][1]=0;
    dfs(1,1,1,0);
    return 0;
}

说实话是一道很好的搜索题目,同时考察了 (dfs)(bfs)

LGJ NB!!!(破音)

最后,完结撒fa~

原文地址:https://www.cnblogs.com/unknown-year/p/13910905.html