迷宫寻宝(一)
时间限制: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
- 来源
- POJ月赛改编
- 上传者
- 张云聪
-
解题:压缩+dfs1 #include <cstdio> 2 #include <cstring> 3 #include <set> 4 #define LL long long 5 using namespace std; 6 char table[23][23]; 7 int rows,cols,totKey[5],hasKey[5],sx,sy; 8 set<LL>vis; 9 bool isVis(int x,int y){ 10 LL temp = 0; 11 for(int i = 0; i < 5; i++) 12 temp = (temp<<9)+hasKey[i]; 13 temp = (temp<<10)+(x<<5)+y; 14 if(vis.count(temp)) return true; 15 vis.insert(temp); 16 return false; 17 } 18 bool dfs(int x,int y) { 19 if(table[x][y] == 'X') return false; 20 if(table[x][y] == 'G') 21 return true; 22 if(isVis(x,y)) return false; 23 static int dir[4][2] = {0,-1,0,1,-1,0,1,0}; 24 if(table[x][y] >= 'a' && table[x][y] <= 'e') { 25 hasKey[table[x][y]-'a']++; 26 table[x][y] = '.'; 27 } else if(table[x][y] >= 'A' && table[x][y] <= 'E') { 28 if(hasKey[table[x][y]-'A'] < totKey[table[x][y]-'A']) 29 return false; 30 } 31 char ch = table[x][y]; 32 table[x][y] = '.'; 33 for(int i = 0; i < 4; i++) 34 if(dfs(x+dir[i][0],y+dir[i][1])) return true; 35 if(table[x][y] != '.') table[x][y] = ch; 36 return false; 37 } 38 int main() { 39 int i,j; 40 while(scanf("%d %d",&rows,&cols),rows||cols) { 41 memset(totKey,0,sizeof(totKey)); 42 memset(hasKey,0,sizeof(hasKey)); 43 memset(table,'X',sizeof(table)); 44 for(i = 1; i <= rows; i++) { 45 scanf("%s",table[i]+1); 46 table[i][strlen(table[i])]='X'; 47 for(j = 1; j <= cols; j++) { 48 if(table[i][j] == 'S') { 49 table[sx = i][sy = j] = '.'; 50 } else if(table[i][j] >= 'a' && table[i][j] <= 'e') { 51 totKey[table[i][j]-'a']++; 52 } 53 } 54 } 55 vis.clear(); 56 for(i = 0; i < 5; i++) 57 if(!totKey[i]) totKey[i] = 500; 58 printf("%s ",dfs(sx,sy)?"YES":"NO"); 59 } 60 return 0; 61 }