NYOJ迷宫寻宝(一)【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
终于把它AC了微笑
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
char map[25][25];
int vis[25][25],A,B,C,D,E,use[10];
int m,n,mov[][2]={1,0,-1,0,0,1,0,-1};
int BFS(int x,int y){
	int xx,yy,i,j,z;
	queue<int>Q;memset(vis,0,sizeof(vis));
	z=x*m+y;
	Q.push(z);vis[x][y]=1;
	while(!Q.empty()){
		z=Q.front();Q.pop();
		x=z/m;y=z%m;
		for(i=0;i<4;++i){
			xx=x+mov[i][0];
			yy=y+mov[i][1];
			if(xx>=0&&xx<m&&yy>=0&&yy<n&&vis[xx][yy]==0&&map[xx][yy]!='X'){
				if(map[xx][yy]=='.'){
					z=xx*m+yy;Q.push(z);vis[xx][yy]=1;
				}
				else if(map[xx][yy]=='G')return 1;
				else if(map[xx][yy]=='a'){A--;z=xx*m+yy;Q.push(z);vis[xx][yy]=1;map[xx][yy]='.';} 
				else if(map[xx][yy]=='b'){B--;z=xx*m+yy;Q.push(z);vis[xx][yy]=1;map[xx][yy]='.';}
				else if(map[xx][yy]=='c'){C--;z=xx*m+yy;Q.push(z);vis[xx][yy]=1;map[xx][yy]='.';}
				else if(map[xx][yy]=='d'){D--;z=xx*m+yy;Q.push(z);vis[xx][yy]=1;map[xx][yy]='.';}
				else if(map[xx][yy]=='e'){E--;z=xx*m+yy;Q.push(z);vis[xx][yy]=1;map[xx][yy]='.';}
				else if(map[xx][yy]=='A'){
					if(A==0){z=xx*m+yy;Q.push(z);vis[xx][yy]=1;}
				}
				else if(map[xx][yy]=='B'){
					if(B==0){z=xx*m+yy;Q.push(z);vis[xx][yy]=1;}
				}
				else if(map[xx][yy]='C'){
					if(C==0){z=xx*m+yy;Q.push(z);vis[xx][yy]=1;}
				}
				else if(map[xx][yy]=='D'){
					if(D==0){z=xx*m+yy;Q.push(z);vis[xx][yy]=1;}
				}
				else if(map[xx][yy]=='E'){
					if(E==0){z=xx*m+yy;Q.push(z);vis[xx][yy]=1;}
				}
			}
		}
	}
	return 0; 
}
int main()
{
	int i,j,k,startx,starty,endx,endy;
	while(scanf("%d%d",&m,&n)==2){
		if(m==0&&n==0)break;
		A=B=C=D=E=0;getchar();
		for(i=0;i<m;++i){
			scanf("%s",map[i]);
			for(j=0;j<n;++j){
				if(map[i][j]=='S'){
					startx=i;starty=j;map[i][j]='.';
				}
				else if(map[i][j]=='a')A++;
				else if(map[i][j]=='b')B++;
				else if(map[i][j]=='c')C++;
				else if(map[i][j]=='d')D++;
				else if(map[i][j]=='e')E++;
			}
		}int whither,ok=1;memset(use,0,sizeof(use));
		if(A==0)use[1]=1;
		else if(B==0)use[2]=1;
		else if(C==0)use[3]=1;
		else if(D==0)use[4]=1;
		else if(E==0)use[5]=1;
		whither=BFS(startx,starty);
		if(whither==1){
			printf("YES\n");
		}
		else{
			while(1){
					if(A==0&&use[1]==0){
						whither=BFS(startx,starty);
						use[1]=1;if(whither)break;
					}
					else if(B==0&&use[2]==0){
						whither=BFS(startx,starty);
						use[2]=1;if(whither)break;
					}
					else if(C==0&&use[3]==0){
						whither=BFS(startx,starty);
						use[3]=1;if(whither)break;
					}
					else if(D==0&&use[4]==0){
						whither=BFS(startx,starty);
						use[4]=1;if(whither)break;
					}
					else if(E==0&&use[5]==0){
						whither=BFS(startx,starty);
						use[5]=1;if(whither)break;
					}
					else break;
			}
			if(whither==1){
				printf("YES\n");
			}
			else printf("NO\n");
		}
	}
	return 0;
}        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值