1321: 营救公主

时间限制: 1 Sec  内存限制: 128 MB
提交: 156  解决: 37
[提交][状态][讨论版]

题目描述

DSKer今天又做梦了,他的睡眠质量一直很差。他梦见他化身骑士(不存在),去营救公主。
公主被困在一个迷宫里。迷宫里有N个编过号的门(N<=5),它们分别被编号为A,B,C,D,E.为了救出公主,DSKer必须打开门,但是,开门之前必须在迷宫里找到这个打开这个门所需的所有钥匙(每个门都至少有一把钥匙),例如:现在A门有三把钥匙,DSKer就必须找全三把钥匙才能打开A门。
现在请你编写一个程序来告诉DSKer,他能不能顺利救出公主。

 

输入

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

 

输出

每组数据输出一个YES表示DSKer能救出公主,输出NO表示他不能救出公主。

 

样例输入

4 4 
S.X. 
a.X. 
..XG 
.... 
3 4 
S.Xa 
.aXB 
b.AG 
0 0

样例输出

YES 
NO
 1 // key[] : 钥匙的总共个数
 2 // num[] : 每次搜索能够得到的钥匙数
 3 // isok[]: 能否得到所有的钥匙数
 4 // 思路: 反复搜索,直到当地图无法改变(有一个大门可以解锁)或者可以到达重点
 5 #include <bits/stdc++.h>
 6 using namespace std;
 7 const int N=30;
 8 char str[N][N];
 9 bool visit[N][N];
10 int  key[10],num[10];  
11 bool isok[10];         
12 int n,m;
13 int s_x,s_y;
14 bool flag,change;
15 int dx[]={0,0,-1,1};
16 int dy[]={1,-1,0,0};
17 bool iskey (char c) {
18     if (c>='a'&&c<='e') return 1;
19     return 0;
20 }
21 bool isok1(int x,int y) {
22     if (x>=1&&x<=n&&y>=1&&y<=m&&str[x][y]!='X')
23         return 1;
24     return 0;
25 } 
26 bool dfs (int x,int y) {
27     visit[x][y]=1;
28     if (str[x][y]=='G') return 1;
29     for (int i=0;i<4;i++) {
30         int tx=x+dx[i];
31         int ty=y+dy[i];
32         if (isok1(tx,ty)&&!visit[tx][ty])  {
33             if (str[tx][ty]>='A'&&str[tx][ty]<='E') {
34                 if (isok[str[tx][ty]-'A']&&dfs(tx,ty))
35                     return 1;
36             }
37             else {
38                 if ( iskey(str[tx][ty]) ) 
39                     num[str[tx][ty]-'a']++;  //小错误不要犯 (tx,ty)写成(x,y)
40                 if (dfs(tx,ty)) return 1;
41             }
42         }
43     }
44     return 0;
45 }
46 int main ()
47 {
48     while (~scanf ("%d %d\n",&n,&m)&&n&&m) {
49         memset (isok,0,sizeof(isok));
50         memset (key,0,sizeof(key));
51         for (int i=1;i<=n;i++) {
52             gets(str[i]+1);
53             for (int j=1;j<=m;j++) {
54                 if (str[i][j]=='S')   {
55                     s_x=i;
56                     s_y=j;
57                 }
58                 if (iskey(str[i][j])) 
59                     key[str[i][j]-'a']++;
60             }
61         }
62         flag=0;
63         while (1) {
64             change=0;
65             memset (visit,0,sizeof(visit));
66             memset (num,0,sizeof(num));
67             if (dfs(s_x,s_y)) {
68                 flag=1; break;
69             }
70             for (int i=0;i<5;i++) {
71                 if (key[i]>0&&key[i]==num[i])
72                     if (!isok[i]) {
73                         change=1;
74                         isok[i]=1;
75                     }
76             }
77             if (!change) break;
78         }
79         if (flag)  puts("YES");
80         else       puts("NO");
81     }
82     return 0;
83 }

继续加油。。。。。做题总是会想起你。mt