2016 UESTC Training Search Algorithm and StringB - Xiper的奇妙历险(2)(三维迷宫)

题目链接:http://acm.uestc.edu.cn/#/contest/show/99

B - Xiper的奇妙历险(2)

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

转眼间,已经过了10年。 Xiper 和日天都以优异的成绩,从UESTC毕业了。毕业之后, Xiper 每天勤奋地写代码。然而不知为何, Xiper 总觉得自己的智商越来越低了。久而久之, Xiper 对日天产生了怀疑。经过的一番调查, Xiper 发现日天竟然在程序里下毒!日天面对 Xiper 和前来拘留他的潘警察,假意痛哭流涕,并要求 Xiper 亲手给带上手铐。然而就在 Xiper 准备给日天带上手铐时,日天微微一笑,竟从背后掏出了一条咸鱼!“我不做人啦, Xiper !”

title

潘警官赶忙掏出光剑,向日天砍去。不料成为咸鱼王的日天已然是刀枪不入,毫发无损。面对强大的日天, Xiper 丝毫不慌,他示意潘警官在豪宅外守候,自己只身迎战。在 Xiper 的智商碾压之下,日天被诱入火海之中。被火焰包围的日天发出一阵阵的惨叫声,怕是药丸。现在,已经打败了日天的 Xiper 要尽快逃出这间在熊熊燃烧的祖传豪宅。为了简化问题,我们将房子简化成一个 N 层楼,每层楼对应一个 L R 列的网格图,并用不同的字符表示每个格点的状态。

  • . —— 表示该位置为空。 x —— 表示该位置上有障碍,不能移动。 U —— 表示上楼的楼梯入口。 D —— 表示下楼的楼梯入口。 X —— 表示 Xiper 现在所在的位置。 Y —— 表示 Xiper 要到达的出口的位置,保证在第一层楼的边界上。

每秒 Xiper 可以向前后左右移动一格,或者从楼梯的入口到对应的出口。 Xiper 不能移动到边界外的地方,也不能移动到障碍上。保证顶楼没有上楼入口,底层没有下楼入口,每个下楼入口对应的出口只会是上楼入口或者障碍,反之亦然。一个上楼入口只会对应一个下楼入口,且所在层数相邻,所处的行和列一致,反之亦然。注意,同一层楼可能存在多个楼梯;当楼梯入口对应的出口被障碍堵住时, Xiper 就无法到达出口的位置了。现在 Xiper 想知道,他最少要用多少时间能逃出来?

Input

第一行三个数字 N L R(1<=N,L,R<=50) ,表示豪宅的大小。接下来从第 1 层开始依次输入;对于每一层,用 L 行个长度为 R 的字符串表示该层的状态。

Output

如果可以到达,输出一个数 STEP ,表示所需最少的步数。否则输出 1

这里的Xiper和日天都是UESTC校队的的成员,总是喜欢出一些带黑故事的题。。。

题意很好理解,一个典型的三维迷宫,途中设置了障碍,和上下楼梯口;但是请注意,到达楼梯口并不意味着一定上下楼;

迷宫问题找最短路优先考虑bfs,三维bfs只不过比二维的bfs多了两种状态转移方向而已,所以只要你入门了,会用bfs找最短路,不管是几维迷宫都可以搞定;

#include<bits/stdc++.h>
using namespace std;
#define MAXN 55
char s[MAXN][MAXN][MAXN];
int visit[MAXN][MAXN][MAXN];//记忆化数组 
struct node{
	int n,l,r,step;
}start;
struct node2
{
	int dl,dr;
}dre[4];
int n,l,r;
int bfs(struct node start)
{
	int i;
	queue<node> q;
	q.push(start);//初始状态入队 
	while(!q.empty())
	{
		struct node x=q.front();	
		q.pop();
		if(s[x.n][x.l][x.r]=='Y')
		return x.step;
		for(i=0;i<4;i++)//前后左右 
		{
			int nn=x.n;
			int ll=x.l+dre[i].dl;
			int rr=x.r+dre[i].dr;
			if(ll<l&&ll>=0&&rr<r&&rr>=0&&!visit[nn][ll][rr]&&s[x.n][ll][rr]!='x')//判断是否合法 
			{
				struct node y=x;
				y.step++;
				y.l=ll;
				y.r=rr;
				visit[nn][ll][rr]=1;
				q.push(y);
			}
		}
		if(s[x.n][x.l][x.r]=='U'&&s[x.n+1][x.l][x.r]!='x'&&!visit[x.n+1][x.l][x.r])//上楼 
		{
			struct node y=x;
			y.n++;
			y.step++;
			visit[y.n][y.l][y.r]=1;
			q.push(y);
		}
		else if(s[x.n][x.l][x.r]=='D'&&s[x.n-1][x.l][x.r]!='x'&&!visit[x.n-1][x.l][x.r])//下楼 
		{
			struct node y=x;
			y.n--;
			y.step++;
			visit[y.n][y.l][y.r]=1;
			q.push(y);
		}
	}
	return -1;
}
int main()
{
	int i,j,k,flag=1;
	char ch;
	scanf("%d%d%d",&n,&l,&r);
	memset(visit,0,sizeof(visit));
	dre[0].dl=0;//方向数组 
	dre[0].dr=1;
	dre[1].dl=1;
	dre[1].dr=0;
	dre[2].dl=-1;
	dre[2].dr=0;
	dre[3].dl=0;
	dre[3].dr=-1;
	for(i=0;i<n;i++)
	{
		for(j=0;j<l;j++)
		{
			scanf("%s",s[i][j]);
			for(k=0;k<r&&flag;k++)
			{
				if(s[i][j][k]=='X')
				{
					start.n=i;
					start.l=j;
					start.r=k;
					start.step=0;
					flag=0;
					break;
				}
			}	
		}
	}
	visit[start.n][start.l][start.r]=1;
	printf("%d",bfs(start));
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值