宽搜——Dungeon Master

题目:

 PS:懒得看的话直接拉下去看题目大意

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迷宫里面,S表示起点,E表示终点,. 表示可走的地方,走每一步需要一分钟,求脱困的最短时间

题目不难,不过有个坑——迷宫不止一条路能出去,因此要找的是最短路而不是找路。若认为这题只有一条路,用深搜,恭喜你wa了。 由于数据范围较大,即使用回溯法dfs也会超时,因此只能BFS。

下面附上代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int L,R,C,ans;
char map[35][35][35];
int vis[35][35][35];		//标记走过的地方用于剪枝 
int dl[]={-1,1,0,0,0,0};  	//六个方向 
int dr[]={0,0,-1,1,0,0};  
int dc[]={0,0,0,0,-1,1}; 




struct point
{
	int L;
	int R;
	int C;
	int num;//记录当前走到第几步 
	
	point(int l=0,int r=0,int c=0,int n=0)
	{//最近才学到原来结构体也可以有构造函数-_-|| 
		L = l;
		R = r;
		C = c;
		num = n;
	}
	~point(){}
}S,a;
queue<point> que;




int main()
{
	while(cin>>L>>R>>C&&(L||C||R))
	{
		memset(map,0,sizeof(map));
		memset(vis,0,sizeof(vis));
		while(!que.empty())//上次终点时队列为非空,清空队列 
			que.pop();
		ans = 999999999;
		for(int i=1;i<=L;i++)
			for(int j=1;j<=R;j++)
				for(int k=1;k<=C;k++)
				{
					cin>>map[i][j][k];
					if(map[i][j][k]=='S')
					{
						S.L = i;
						S.R = j;
						S.C = k;
					}
				}
					
		que.push(point(S.L,S.R,S.C,0));
		int k = 1;//标记能否走到终点
		while(k&&!que.empty())
		{
			a = que.front();
			que.pop();
			for(int i=0;i<6;i++)
			{//搜索六个方向 
				if(vis[a.L+dl[i]][a.R+dr[i]][a.C+dc[i]]==0&&(map[a.L+dl[i]][a.R+dr[i]][a.C+dc[i]]=='.'||map[a.L+dl[i]][a.R+dr[i]][a.C+dc[i]]=='E'))
				{
					if(map[a.L+dl[i]][a.R+dr[i]][a.C+dc[i]]=='E')
					{//下一步是终点了 
						ans = min(a.num+1,ans);//这步应该多余了,宽搜到的一定是最短路 
						k = 0; //标记能否走到终点
						break;
					}
					vis[a.L+dl[i]][a.R+dr[i]][a.C+dc[i]] = 1;
					que.push(point(a.L+dl[i],a.R+dr[i],a.C+dc[i],a.num+1));
				}	
			}	
		}		
		if(k)
			ans = 0;
		if(ans)	
			printf("Escaped in %d minute(s).\n",ans);
		else
			printf("Trapped!\n");
	}
}

宽搜最近刚回,总结一下:

  搜索一个节点时,先判断边界条件,不符合直接return,符合则将其进行标记,防止走回头路,然后将其各个子节点插入

队列中,每次从队列中取出一个元素,进行判断;如此反复,直至找到答案或队列为空。

 一定要做标记剪枝!!!

 一定要做标记剪枝!!!

 一定要做标记剪枝!!!

  后果如下







posted @ 2018-02-02 23:18  Apale  阅读(252)  评论(0编辑  收藏  举报