nyoj迷宫寻宝(一)

  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                 
View Code

解题思路:

记录某种钥匙总数(即剩余未访问到的钥匙数),记录开始位置并入队,利用广搜,从开始位置进行搜索,进行逐个出队判断:

1:如果找到某把钥匙,则剩余这种钥匙数减1,并进行判断:这种钥匙是否已找到完,这种钥匙所对应的门是否以找到,如果两个条件都满足,则把该门入队。然后把钥匙位置标记已遍历,对其相邻点进行广搜;

2:如果找到某个门并且其钥匙没有找到全部,则标记记录门的位置;

3:如果找到宝藏,则返回1,表示成功找到宝藏;

4:如果为开始位置'S'、可走位置'.'、已找到全部钥匙的门,则将其标记为已遍历,对其相邻点进行广搜;

5:如果该位置为墙'X',则将其跳过不便利;

如果队列为空,则说明在找到宝藏之前无可遍历位置,则返回0,表示未能找到宝藏;

原文地址:https://www.cnblogs.com/WDKER/p/5380226.html