M-A计划(两层迷宫)

文章描述了一个编程竞赛中的题目,迷宫中有时空传输机,勇士们需找到被关的fish。题目要求在限定时间内使用DFS或BFS搜索路径,要考虑传送门导致的层间移动和循环。作者分享了使用C++实现的BFS解题思路,包括三维数组记录地图、判断条件和搜索过程。
摘要由CSDN通过智能技术生成

简单搜索&&进阶搜索 - Virtual Judge (vjudge.net)

【题目描述】

fish被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),fish的位置用P表示,时空传输机用# 表示,墙用*表示,平地用.表示。勇者们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那勇者们就会被撞死。勇者们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。

【输入】

输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N* M(1 <= N,M <=10) 。T如上所意。接下去的前N* M表示迷宫的第一层的布置情况,后N* M表示迷宫第二层的布置情况。

【输出】

如果勇者们能够在T时刻能找到fish就输出“YES”,否则输出“NO”。

解题思路

这个题写了好久,刚开始用的 dfs 写的,我以为是效率很低所以过不了,但是后面改成 bfs 还是没过,主要是有条件没判断:从一层传到另一层时,此时不能为‘ * ’,传到的地方是墙肯定不行,而且不能是‘ # ’,如果到达的地方也是传送门的话,就是个循环,出不来了,这个情况也要考虑。

这个题是在原本的搜索上加上了传送门,所以在遍历的时候也是定义应该二维 dir 的方向数组,分别代表 x 轴和 y 轴的方向。

我是用 a[tz][ty][tx] 记录的地图,其中 tz 是层数,ty 是行数,tx 是列数。

用 book 数组记录该点是否走到,然后遇到传送门‘ # ’,就更改 tz 的值,并且判断另外一层是否能到:

我是用一个三维数组存放地图,在走到传送门 ‘#’ 时,将地图的层数改变,并且将

					if (a[tz][ty][tx] == '#')
					{
						tz = tz ? 0 : 1;
						if (a[tz][ty][tx] == '*'||a[tz][ty][tx]=='#')
							continue;
					}

代码:

#include<stdio.h>
#include<string.h>
int time, n, m;
char a[15][15][15];
int book[15][15][15];
struct node
{
	int x;//列数
	int y;//行数
	int z;//层数
	int t;//步数
};
struct node k[10000];
int main()
{
	int t, i, j;
	scanf("%d", &t);
	while (t--)
	{
		int flag = 0;
		scanf("%d%d%d", &n, &m, &time);
		for (i = 0; i < n; i++)
			scanf("%s", a[0][i]);
		for (i = 0; i < n; i++)
			scanf("%s", a[1][i]);
		int head = 0, tail = 0;
		int dir[4][2] = { 0,1,0,-1,1,0,-1,0 };
		k[tail].x = 0;
		k[tail].y = 0;
		k[tail].z = 0;
		k[tail].t = 1;
		book[0][0][0] = 1;
		tail++;
		while (head < tail)
		{
			for (i = 0; i < 4; i++)
			{
				int tx = k[head].x + dir[i][0];
				int ty = k[head].y + dir[i][1];
				int tz = k[head].z;
				if (tx < 0 || tx >= m || ty < 0 || ty >= n)//超出地图的范围就去掉这种情况
					continue;
				if (book[tz][ty][tx] == 0 && a[tz][ty][tx] != '*')//没到墙壁‘*’,就接着判断是否可以加入队列
				{
					book[tz][ty][tx] = 1;//先把该点标记
					if (a[tz][ty][tx] == '#')//传送门
					{
						tz = tz ? 0 : 1;
						if (a[tz][ty][tx] == '*'||a[tz][ty][tx]=='#')//这种情况也要考虑
							continue;
					}
					book[tz][ty][tx] = 1;//接着把通过传送门的地图也标记,防止重复查找
					k[tail].x = tx;
					k[tail].y = ty;
					k[tail].z = tz;
					k[tail].t = k[head].t + 1;//加入队列
					tail++;
				}
				if (a[tz][ty][tx] == 'P')//达到终点的情况
				{
					flag = 1;//设置一个标记,在bfs中若是找到终点,此时一定是最短步数的情况之一
					if (k[head].t <= time)//如果该点不满足条件,说明不能在规定时间找到终点
						flag = 2;
					break;
				}
			}
			if (flag == 1||flag==2)
				break;
			head++;
		}
		if (flag == 2)
			printf("YES\n");
		else
			printf("NO\n");
		memset(book, 0, sizeof(book));//循环输出,要把book数组里的值初始化
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明里灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值