CDOJ 1088 王之迷宫 BFS

16 篇文章 0 订阅

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

王被困在了一个3维的迷宫中,他很想逃离这个迷宫回去当学霸,你能帮助他么? 由于王很仁慈,他悄悄地告诉你,本题读入迷宫的每一行时,要用scanf("%s"...) ......

Input
多组测试数据,对于每组测试数据,有三个整数 L,R,C(0<l,r,c≤30)。
L代表迷宫的高度,R和C分别代表每一层的行和列。
接下来是L个R×C的矩阵,矩阵包含4种字符(S,E,.,#),S代表王的初始位置,E代表出口,#代表障碍。.代表能通过的地方。
每一层之后有一个空行。
当L=R=C=0时,输入中断。

Output
如果可以逃离迷宫,按下列格式输出最短时间:
Escaped in x minute(s). (x表示逃离迷宫的最短时间, 走一步花费一昏钟)
否则,输出:
Trapped!

Sample Input

3 4 5
S....
.###.
.##..
###.#


#####
#####
##.##
##...


#####
#####
#.###
####E


1 3 3
S##
#E#
###


0 0 0

Sample Output

Escaped in 11 minute(s).
Trapped!


原理不难,首先用三维数组map读入这个地图,读入过程中找到起点S,记录下它的位置并把它改为’#’,因为以后搜索时肯定就不会再往起点走了。

然后写BFS,首先写个队列,我是用结构数组来当队列的,存储位置和走到这里用的时间。
然后先把起点入队,之后用尾指针tail把起点六个方向中能走到的地方入队,并且把能走到的地方在map上标记为’#’,因为是找最短时间,所以之后的路中就不会走已走过的路了。然后判断头指针的位置是不是出口’E’,不是的话就移动头指针,继续向下搜索。如此这样,直到找到出口。如果把能走的路都已走完的话,尾指针tail就不会再移动,然后头指针一直也移动到与尾指针相同时,便把所有能走到的地方遍历了一遍,如果没有找到出口,就返回0,表示Trapped!。
需要注意的就是输入输出用scanf(“%s”…)就行,因为每行之间是空白,scanf忽略空白。

另外对于每次地图,查询完之后,要清空数据,防止影响下组数据。

手写的队列,手写的BFS,一开始WA了半天,WA在了判断能否找到出口那,那个判断条件,一开始我写的head==tail,但是tail是下一次的入队的元素的下标。所以应该是head==tail-1。tail-1是当前队列的最后一个元素的坐标。

AC代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int l = 0, r = 0, c = 0, total = 0;//lrc为地图长宽高
int head = 0, tail = 1;//头尾指针
char map[32][32][32] = { '\0' };
int blank[3] = { 0 };//存储入口
struct queue
{
	int fst;
	int snd;
	int trd;
	int cnt;
}que[1000000];//队列


bool move(int set, int pos, int i, int j, int k)
{
	if (i >= 0 && j >= 0 && k >= 0 && i<l && j<r && k< c && map[i][j][k] != '#')
	{
		que[pos].fst = i;//存储位置
		que[pos].snd = j;
		que[pos].trd = k;
		que[pos].cnt = que[set].cnt + 1;//存储时间
		if (map[i][j][k] != 'E')//记忆化,有人走过的地方就不再走了
			map[i][j][k] = '#';
		return true;
	}
	else return false;
}

int BFS(int i, int j, int k)
{
	que[0].cnt = 0; que[0].fst = blank[0]; que[0].snd = blank[1]; que[0].trd = blank[2];
	if (move(head, tail, i + 1, j, k))//往下搜索
		tail++;
	if (move(head, tail, i - 1, j, k))
		tail++;
	if (move(head, tail, i, j + 1, k))
		tail++;
	if (move(head, tail, i, j - 1, k))
		tail++;
	if (move(head, tail, i, j, k + 1))
		tail++;
	if (move(head, tail, i, j, k - 1))
		tail++;
	if (head == tail-1)//遍历之后没有找到
	{
		//		printf("trap-head%d\n", head);
		return 0;
	}
	else
	{
		head++;
		if (map[que[head].fst][que[head].snd][que[head].trd] == 'E')//找到出口
		{
			//			printf("tail%d\n", tail);
			return que[head].cnt;
		}
		else
		{
			return BFS(que[head].fst, que[head].snd, que[head].trd);//继续搜索
		}
	}
}

int main()
{
	int ans = 0;
	memset(map, 0, sizeof(map));
	memset(que, 0, sizeof(que));
	while (scanf("%d %d %d", &l, &r, &c))//输入长宽高
	{
		if (l == 0 && r == 0 && c == 0) break;
		total = l*r*c;
		for (int i = 0; i < l; i++)//输入地图
		{
			for (int j = 0; j < r; j++)
			{
				scanf("%s", map[i][j]);
				for (int k = 0; k < c; k++)
				{
					if (map[i][j][k] == 'S')
					{
						map[i][j][k] = '#';//存储入口
						blank[0] = i; blank[1] = j; blank[2] = k;
					}
				}
			}
			
		}
		ans = BFS(blank[0], blank[1], blank[2]);//搜索
		if (ans > 0)//输出
		{
			printf("Escaped in %d minute(s).\n", ans);
		}

		else printf("Trapped!\n");
		head = 0; tail = 1; ans = 0;//清空数据
		memset(map, 0, sizeof(map));
		memset(que, 0, sizeof(que));
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值