POJ2251 Dungeon Master BFS

Description

You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides. 

Is an escape possible? If yes, how long will it take? 

Input

The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size). 
L is the number of levels making up the dungeon. 
R and C are the number of rows and columns making up the plan of each level. 
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a '#' and empty cells are represented by a '.'. Your starting position is indicated by 'S' and the exit by the letter 'E'. There's a single blank line after each level. Input is terminated by three zeroes for L, R and C.

Output

Each maze generates one line of output. If it is possible to reach the exit, print a line of the form 
Escaped in x minute(s).

where x is replaced by the shortest time it takes to escape. 
If it is not possible to escape, print the line 
Trapped!

Sample Input

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

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

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

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

0 0 0

Sample Output

Escaped in 11 minute(s).
Trapped!

仍然是一个走迷宫的问题,只不过这回变成了3D迷宫,万变不离其宗,当然还是要搜索,但考虑到题目要求输出走出迷宫的最短路线长度,而不是简单的判断是否可以走出,所以我们这里使用BFS,虽然题目并不难,但一开始图简单,就用的queue,加上动态创建结构体对象,结果华丽超时,无奈又重新自己写了一个队列,本想省点空间,结果看起来还是时间比较珍贵,这里的输入要稍微注意一下,如果是cin没有什么,但如果使用scanf,就需要用getchar()吸收掉回车,否则读入的地图是完全混乱的,BFS里计算步数是通过计算树的高度实现的,这个很好理解,BFS本身就是一层一层向下找,因此没走一层就相当于走了一步,六个方向依然是通过数组+循环实现,这里,首先上超时的代码,因为我觉得很省空间

#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
char map[31][31][31];
int dirx[6]={0,0,0,0,-1,1};
int diry[6]={0,0,-1,1,0,0};
int dirz[6]={1,-1,0,0,0,0};
int step;
int visited[31][31][31];
int l,r,c;
struct Point
{
	Point(int l,int r,int c,int d)
	{
		x=r;
		y=c;
		z=l;
		deep=d;
	}
	int x,y,z,deep;
};
bool BFS(int sl,int sr,int sc)
{
	int i;
	bool flag=false;
	queue<Point*> q;
	q.push(new Point(sl,sr,sc,0));
	//Point *a=q.front();
	//cout<<a->x<<' '<<a->y<<' '<<a->z;
	while(!q.empty())
	{
		Point *t=q.front();
		q.pop();
		//cout<<t->z<<' '<<t->x<<' '<<t->y<<endl;
		//cout<<map[t->z][t->x][t->y]<<' ';
		//cout<<t->x<<' '<<t->y<<' '<<t->z<<endl;
		if(map[t->z][t->x][t->y]=='E')
		{
			step=t->deep;
			return true;
		}
		visited[t->z][t->x][t->y]=1;
		for(i=0;i<6;i++)
		{
			int x0,y0,z0,deep0;
			z0=t->z+dirz[i];
			x0=t->x+dirx[i];
			y0=t->y+diry[i];
			deep0=t->deep;
			//cout<<z0<<' '<<x0<<' '<<y0<<endl;
			if(map[z0][x0][y0]!='#'&&visited[z0][x0][y0]==0)
			{
				if(x0>=0&&x0<r&&y0>=0&&y0<c&&z0>=0&&z0<l)
				{
					q.push(new Point(z0,x0,y0,deep0+1));
					
				}
				
			}
		}
		
	}
	return false;
}


int main()
{
	int i,j,k;
	int x,y,z;
	while(scanf("%d%d%d\n",&l,&r,&c)!=EOF,l&&r&&c)
	{
		step=0;
		for(i=0;i<l;i++)
		{
			for(j=0;j<r;j++)
			{
				for(k=0;k<c;k++)
				{
					scanf("%c",&map[i][j][k]);
					visited[i][j][k]=0;
					if(map[i][j][k]=='S')
					{
						x=j;
						y=k;
						z=i;
					}
				}
				getchar();
			}
			getchar();
		}
		for(i=0;i<l;i++)
		{
			for(j=0;j<r;j++)
			{
				for(k=0;k<c;k++)
				{
					cout<<map[i][j][k];
				}
				cout<<endl;
			}
			cout<<endl;
		}
		
		if(BFS(z,x,y))
		{
			cout<<"Escaped in "<<step<<" minute(s)."<<endl;
		}
		else
		cout<<"Trapped!"<<endl;
	}
	return 0;
}
这里要注意三个方向与我们的三维坐标系的对应,可以说有点混乱,主要是因为三维数组虽然可以表示三维空间,但对应不太一样,下面是自己写了队列的正确代码
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
char map[31][31][31];
int dirx[6]={0,0,0,0,-1,1};
int diry[6]={0,0,-1,1,0,0};
int dirz[6]={1,-1,0,0,0,0};
int step;
int visited[31][31][31];
int l,r,c;
struct Point
{
	int x,y,z,deep;
}q[30000];
bool BFS(int sl,int sr,int sc)
{
	int i,rear,front;
	q[0].z=sl;
	q[0].x=sr;
	q[0].y=sc;
	rear=0;
	front=0;
	visited[sl][sr][sc]=1;
	while(front<=rear)
	{

		for(i=0;i<6;i++)
		{
			int x0,y0,z0,deep0;
			z0=q[front].z+dirz[i];
			x0=q[front].x+dirx[i];
			y0=q[front].y+diry[i];
			deep0=q[front].deep;
			if(map[z0][x0][y0]!='#'&&visited[z0][x0][y0]==0)
			{
				if(x0>=0&&x0<r&&y0>=0&&y0<c&&z0>=0&&z0<l)
				{
					visited[z0][x0][y0]=1;
					rear++;
					q[rear].x=x0;
					q[rear].y=y0;
					q[rear].z=z0;
					q[rear].deep=q[front].deep+1;
					
					
					
					if(map[z0][x0][y0]=='E')
					{
						step=q[rear].deep;
						return true;
					}
					
				}
				
			}
		}
		front++;
		
	}
	return false;
}


int main()
{
	int i,j,k;
	int x,y,z;
	while(scanf("%d%d%d",&l,&r,&c)!=EOF,l&&r&&c)
	{
		getchar();
		step=0;
		for(i=0;i<l;i++)
		{
			for(j=0;j<r;j++)
			{
				for(k=0;k<c;k++)
				{
					scanf("%c",&map[i][j][k]);
					visited[i][j][k]=0;
					if(map[i][j][k]=='S')
					{
						x=j;
						y=k;
						z=i;
					}
				}
				getchar();
			}
			getchar();
		}

		
		if(BFS(z,x,y))
		{
			printf("Escaped in %d minute(s).\n",step);
		}
		else
		printf("Trapped!\n");
	}
	return 0;
}
其实写个队列并不是很麻烦,开始为了便于理解我们可以使用STL,但这东西用好了还行,一不留神就会出问题,尤其是时间上的,建议大家尽量避免使用,尤其是在你不知道STL某些容器的时间消耗的时候





你可能感兴趣的:(master,详解,bfs,Dungeon,POJ2251)