NYOJ 82:迷宫寻宝(一)(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


我的思路:先对人进行搜索,再对遇到过且能开的门进行搜索,直到没有门能开或走到终点结束

代码有解析


#include<stdio.h>
#include<string.h>
#include<ctype.h>
typedef struct
{
	int x;
	int y;		/*门的坐标*/
	int key;		/*还要多少个钥匙门才能被打开(>=0)*/
}door;
door s[6];		/*下标1-5对应门A-E*/
int n, m, flag;
char str[22][22], dir[4][2] = {1,0,0,1,-1,0,0,-1};
void Sech(int x, int y);
int main(void)
{
	int i, j, x, y, ip;
	while(scanf("%d%d", &n, &m), n!=0 || m!=0)
	{
		ip = 15;
		flag = 0;
		memset(s, 0, sizeof(s));
		memset(str, 'X', sizeof(str));		/*将迷宫的最外围全部设为'X',这样就不用处理边界*/
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
			{
				scanf(" %c", &str[i][j]);/*用字符输入时记得处理空白符*/
				if(str[i][j]=='S')
					x = i, y = j;
				if(islower(str[i][j]))
					s[str[i][j]-96].key++;		/*如果这个点是钥匙,则对应的钥匙数+1*/
			}
		}
		Sech(x, y);		/*搜索起点*/

		while(ip--)		/*循环多少次都可以,但一定要大于5次(因为最多5个门)*/
		{
			if(flag==1)
				break;
			for(i=1;i<=5;i++)
			{
				if(s[i].key==0 && s[i].x!=0)
					Sech(s[i].x, s[i].y);		/*如果打开这个门还需要0把钥匙,则以这个门为起点进行搜索(此门已破)*/
			}		/*当然,如果某个编号的门并没有被找到,那么这个门的坐标还是默认的(0,0),不会被搜索*/
		}
		if(flag==1)
			printf("YES\n");
		else
			printf("NO\n");
	}
}

void Sech(int x, int y)
{
	int i, c, d;
	if(islower(str[x][y]))
		s[str[x][y]-96].key--;	/*找到钥匙了! 开对应的门所需钥匙数-1*/
	if(str[x][y]=='G')
		flag = 1;			/*找到宝藏,停止搜索*/
	if(flag==1)
		return;
	str[x][y] = 'X';		/*既然来过了,就把他当成'X',没必要再来一遍*/
	for(i=0;i<=3;i++)
	{
		c = x+dir[i][0];
		d = y+dir[i][1];	/*四个方向*/
		if(str[c][d]=='.' || islower(str[c][d]) || str[c][d]=='G')
			Sech(c, d);
		if(str[c][d]>='A' && str[c][d]<='E')			/*(又)找到了一个门,不知道能不能打开,先储存门的坐标,然后遍历完所有能到达的地方以尽可能的找到更多钥匙*/
			s[str[c][d]-64].x = c, s[str[c][d]-64].y = d;
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值