NYOJ82 迷宫寻宝(BFS)

迷宫寻宝(一)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述

一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号的门(N<=5),它们分别被编号为A,B,C,D,E.为了找到宝藏,ACM必须打开门,但是,开门之前必须在迷宫里找到这个打开这个门所需的所有钥匙(每个门都至少有一把钥匙),例如:现在A门有三把钥匙,ACM就必须找全三把钥匙才能打开A门。现在请你编写一个程序来告诉ACM,他能不能顺利的得到宝藏。

 

输入
输入可能会有多组测试数据(不超过10组)。
每组测试数据的第一行包含了两个整数M,N(1<N,M<20),分别代表了迷宫的行和列。接下来的M每行有N个字符,描述了迷宫的布局。其中每个字符的含义如下:
.表示可以走的路
S:表示ACM的出发点
G表示宝藏的位置
X表示这里有墙,ACM无法进入或者穿过。
A,B,C,D,E表示这里是门,a,b,c,d,e表示对应大写字母的门上的钥匙。
注意ACM只能在迷宫里向上下左右四个方向移动。

最后,输入0 0表示输入结束。
输出
每行输出一个YES表示ACM能找到宝藏,输出NO表示ACM找不到宝藏。
样例输入
4 4 
S.X. 
a.X. 
..XG 
.... 
3 4 
S.Xa 
.aXB 
b.AG 
0 0
样例输出
YES 
NO
/*
一路抄袭。终于原创了一次了,尼玛。。。。。不过看了下思路。先广搜,等钥匙找全之后再从头开始进行广搜,不断广搜。。。 加油!!!
Time:2014-10-27 17:38
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAX 22
struct Point{
	int x,y;
}S,E;
char map[MAX][MAX];
bool vis[MAX][MAX];
int N,M;
int kNum[6];
bool door[6];
int move[4][2]={1,0,0,1,-1,0,0,-1};
bool Judge(Point a){
	if(map[a.x][a.y]!='X'&&a.x>=0&&a.x<N&&a.y>=0&&a.y<M)
		return true;
	return false;
}
bool BFS(){
	queue<Point>q;
	int key;
	q.push(S);vis[S.x][S.y]=1;
	Point temp,cur,gate[6];
	while(!q.empty()){
		cur=q.front();q.pop();
		for(int i=0;i<4;i++){
			temp=cur;
			temp.x+=move[i][0];
			temp.y+=move[i][1];
			
			if(!vis[temp.x][temp.y]&&Judge(temp)){
				//printf("%d %d\n",temp.x,temp.y);
				vis[temp.x][temp.y]=true;
				if(map[temp.x][temp.y]>='A'&&map[temp.x][temp.y]<='E'){
					key=map[temp.x][temp.y]-'A';
					gate[key]=temp;
					if(door[key]){
						q.push(temp);
						map[temp.x][temp.y]='.';//开门 
					} 
				}else if(map[temp.x][temp.y]>='a'&&map[temp.y][temp.y]<='e'){
					q.push(temp);
					
					key=map[temp.x][temp.y]-'a';
					map[temp.x][temp.y]='.';//注意和上一行的前后顺序 
					kNum[key]--;
				//	printf("key=%d %d\n",key,kNum[key]);
					if(kNum[key]==0){
						door[key]=true; 
						memset(vis,0,sizeof(vis));
						while(!q.empty())q.pop(); 
						q.push(S);vis[S.x][S.y]=true;
					}
				}else if(map[temp.x][temp.y]=='.'){
					q.push(temp);
				}else if(map[temp.x][temp.y]=='G') return true;
				
			} 
		}
	}
	return false;
}
int main(){
	int i,j;
	while(scanf("%d%d",&N,&M)!=EOF){
		if(N==0&&M==0) break;
		memset(kNum,0,sizeof(kNum));
		memset(vis,0,sizeof(vis));
		memset(map,0,sizeof(map));
		memset(door,0,sizeof(door));
		for(i=0;i<N;i++){
			scanf("%s",map[i]);
			for(j=0;j<M;j++){
				if(map[i][j]>='a'&&map[i][j]<='e'){
					
					kNum[map[i][j]-'a']++;
				}else if(map[i][j]=='S'){
					S.x=i;S.y=j;
				}else if(map[i][j]=='G'){
					E.x=i;E.y=j;
				}
			}
		}
		//printf("%d\n",kNum[0]);
		if(BFS())printf("YES\n");
		else printf("NO\n");
	}
return 0;
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值