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,&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