题意:人走迷宫,起点S,终点G,A/B/C/D/E为门,要开A必须集齐地图上所有的a,依次类推,问最后能否到G。
题解:从起点出发,dfs所有能到的点,其中,遇到门但没凑够钥匙就将该点标记,代表能到它,遇到钥匙就将还需要凑的钥匙减一。然后每次dfs一遍后,查看所有的被标记了的门,如果钥匙够了就从该点出发再进行一次dfs。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cctype> 5 using namespace std; 6 int r,c; 7 char map[30][30]; 8 int num[30],po[30][2]; 9 bool vis[30][30]; 10 bool in(int x,int y) 11 { 12 return (x>=1&&x<=r&&y>=1&&y<=c&&map[x][y]!='X'); 13 } 14 bool dfs(int x,int y) 15 { 16 if(map[x][y]=='G') 17 return true; 18 vis[x][y]=true; 19 if(isupper(map[x][y])&&num[map[x][y]-'A']!=0) 20 return false; 21 if(islower(map[x][y])) 22 num[map[x][y]-'a']--,map[x][y]='.'; 23 bool flag=false; 24 if(in(x+1,y)&&!vis[x+1][y]) 25 flag=flag||dfs(x+1,y); 26 if(in(x-1,y)&&!vis[x-1][y]) 27 flag=flag||dfs(x-1,y); 28 if(in(x,y+1)&&!vis[x][y+1]) 29 flag=flag||dfs(x,y+1); 30 if(in(x,y-1)&&!vis[x][y-1]) 31 flag=flag||dfs(x,y-1); 32 return flag; 33 } 34 int main() 35 { 36 while(scanf("%d%d",&r,&c),(r||c)) 37 { 38 memset(num,-1,sizeof(num)); 39 memset(vis,false,sizeof(vis)); 40 int x,y; 41 for(int i=1;i<=r;i++) 42 { 43 scanf("%s",map[i]+1); 44 for(int j=1;j<=c;j++) 45 { 46 char ch=map[i][j]; 47 if(isalpha(ch)) 48 { 49 if(islower(ch)) 50 { 51 if(num[ch-'a']==-1) 52 num[ch-'a']=1; 53 else 54 num[ch-'a']++; 55 } 56 else if(ch<='E') 57 { 58 po[ch-'A'][0]=i; 59 po[ch-'A'][1]=j; 60 if(num[ch-'A']==-1) 61 num[ch-'A']=0; 62 } 63 else if(ch=='S') 64 { 65 x=i;y=j; 66 map[i][j]='.'; 67 } 68 } 69 } 70 } 71 if(dfs(x,y)) 72 { 73 printf("YES\n"); 74 continue; 75 } 76 while(1) 77 { 78 bool flag=false; 79 for(int i=0;i<5;i++) 80 { 81 if(num[i]==0) 82 { 83 x=po[i][0]; 84 y=po[i][1]; 85 if(!vis[x][y]) 86 continue; 87 num[i]--; 88 flag=true; 89 map[x][y]='.'; 90 break; 91 } 92 } 93 if(!flag) 94 { 95 printf("NO\n"); 96 break; 97 } 98 else if(dfs(x,y)) 99 { 100 printf("YES\n"); 101 break; 102 } 103 } 104 } 105 return 0; 106 }