1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 7 using namespace std; 8 struct node{ 9 int x,y; 10 }; 11 queue<node> q; 12 char maze[25][25]; //地图 13 int key[5];//记录钥匙个数; 14 node door[5];//门的位置; 15 node D;//起始位置 16 17 void add(int i,int j) //第四个方向遍历 18 { 19 D.x=i+1; 20 D.y=j; 21 if('X'!=maze[D.x][D.y]) 22 q.push(D); 23 D.x=i-1; 24 D.y=j; 25 if('X'!=maze[D.x][D.y]) 26 q.push(D); 27 D.x=i; 28 D.y=j+1; 29 if('X'!=maze[D.x][D.y]) 30 q.push(D); 31 D.x=i; 32 D.y=j-1; 33 if('X'!=maze[D.x][D.y]) 34 q.push(D); 35 } 36 37 int BFS() 38 { 39 int i,j; 40 memset(door,0,sizeof(door)); 41 while(!q.empty()) 42 { 43 D=q.front(); 44 q.pop(); 45 i=D.x; j=D.y; //记录当前位置 46 if('a'==maze[i][j]||'b'==maze[i][j]||'c'==maze[i][j]||'d'==maze[i][j]||'e'==maze[i][j])//如果为钥匙则-1; 47 { 48 key[maze[i][j]-'a']--; 49 if(key[maze[i][j]-'a']==0&&door[maze[i][j]-'a'].x!=0&&door[maze[i][j]-'a'].y!=0)//如果之前访问过此屋,并且钥匙以全找到 则加入队列 50 q.push(door[maze[i][j]-'a']); 51 maze[i][j]='X'; 52 add(i,j); 53 } 54 else 55 { 56 if(('E'==maze[i][j]||'B'==maze[i][j]||'C'==maze[i][j]||'D'==maze[i][j]||'A'==maze[i][j])&&0!=key[maze[i][j]-'A']) //为房屋并且此房屋钥匙没全找到,记录此位置。 57 door[maze[i][j]-'A']=D; 58 else 59 if('G'==maze[i][j]) //找到返回 60 return 1; 61 else 62 if('X'!=maze[i][j])//可以走的位置。 63 { 64 maze[i][j]='X'; 65 add(i,j); 66 } 67 } 68 } 69 return 0; 70 } 71 72 73 int main() 74 { 75 int m,n,i,j; 76 while(scanf("%d%d",&m,&n)&&(m!=0||n!=0)) 77 { 78 memset(maze,'X',sizeof(maze)); 79 memset(key,0,sizeof(key)); 80 for(i=1;i<=m;i++) 81 { 82 scanf("%s",&maze[i][1]); 83 for(j=1;j<=n;j++) 84 { 85 if(maze[i][j]=='a'||maze[i][j]=='b'||maze[i][j]=='c'||maze[i][j]=='d'||maze[i][j]=='e') 86 key[maze[i][j]-'a']++; 87 else{ 88 if('S'==maze[i][j]) 89 { 90 D.x=i; D.y=j; q.push(D); 91 } 92 } 93 } 94 } 95 if(BFS()) 96 printf("YES "); 97 else 98 printf("NO "); 99 } 100 return 0; 101 } 102 103
解题思路:
记录某种钥匙总数(即剩余未访问到的钥匙数),记录开始位置并入队,利用广搜,从开始位置进行搜索,进行逐个出队判断:
1:如果找到某把钥匙,则剩余这种钥匙数减1,并进行判断:这种钥匙是否已找到完,这种钥匙所对应的门是否以找到,如果两个条件都满足,则把该门入队。然后把钥匙位置标记已遍历,对其相邻点进行广搜;
2:如果找到某个门并且其钥匙没有找到全部,则标记记录门的位置;
3:如果找到宝藏,则返回1,表示成功找到宝藏;
4:如果为开始位置'S'、可走位置'.'、已找到全部钥匙的门,则将其标记为已遍历,对其相邻点进行广搜;
5:如果该位置为墙'X',则将其跳过不便利;
如果队列为空,则说明在找到宝藏之前无可遍历位置,则返回0,表示未能找到宝藏;