一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号的门(N<=5),它们分别被编号为A,B,C,D,E.为了找到宝藏,ACM必须打开门,但是,开门之前必须在迷宫里找到这个打开这个门所需的所有钥匙(每个门都至少有一把钥匙),例如:现在A门有三把钥匙,ACM就必须找全三把钥匙才能打开A门。现在请你编写一个程序来告诉ACM,他能不能顺利的得到宝藏。
4 4 S.X. a.X. ..XG .... 3 4 S.Xa .aXB b.AG 0 0
YES NO
解题:压缩+dfs
1 #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\n",dfs(sx,sy)?"YES":"NO"); 59 } 60 return 0; 61 }