HDU 5025 Saving Tang Monk【bfs搜索】【北大ACM/ICPC竞赛训练】

bfs的难点在于怎么去表示一个问题的状态【也就是如何去判重】

对于这种情况,每个状态有【守卫当前状态】、【已有钥匙】、【位置r和c】和【已花时间】。那么对于判重来说,我们记录守卫、钥匙、位置这三个状态就行了。(比如说一个位置可以重复走,因为可能拿了钥匙后再走回来;一个位置可以重复走,因为可能在这个点上守卫存活状况不同)

  1 #include<iostream>
  2 #include<queue>
  3 #include<cstring>
  4 #include<map>
  5 using namespace std;
  6 
  7 struct node{
  8     int r,c;
  9     int keys; 
 10     int kill;//记录当前杀死守卫的状态 
 11     int d;//时间
 12     bool operator < (const node n2) const{
 13         return d>n2.d;
 14     } 
 15     node(int r1,int c1,int k1,int k2,int d1): r(r1),c(c1),keys(k1),kill(k2),d(d1) {}
 16 };    
 17 
 18 priority_queue<node> q;//默认大根堆 
 19 
 20 char maze[105][105];
 21 int dx[4]={0,0,1,-1};
 22 int dy[4]={1,-1,0,0};
 23 bool vis[105][105][10][32];//vis[i][j][k][l]为有没有杀死【l所代表的守卫】拿着1-k的钥匙到过(i,j) 
 24 
 25 int snakeID[105][105];
 26 
 27 int main(){
 28     //cout<<int('9')<<endl;
 29     while(1){
 30         int n,m; cin>>n>>m;//m把钥匙
 31         if(n==0 && m==0) break;
 32         int startr,startc,endr,endc;
 33         bool save=false;
 34         
 35         memset(vis,0,sizeof(vis));
 36         
 37         int id=0;
 38         for(int i=1;i<=n;i++)
 39             for(int j=1;j<=n;j++){
 40                 cin>>maze[i][j];
 41                 if(maze[i][j]=='T') { endr=i; endc=j; }
 42                 else if(maze[i][j]=='K') { startr=i; startc=j; }
 43                 else if( maze[i][j]=='S' ) snakeID[i][j]= ++id;//在这个位置蛇的编号 
 44         }
 45         
 46         //'.' means a clear room as well 
 47         q.push( node(startr,startc,0,0,0) ); 
 48         vis[startr][startc][0][0]=1;//不能走了 
 49         
 50         while(!q.empty()){
 51             node n1 = q.top(); q.pop();
 52             if(n1.r==endr && n1.c==endc && n1.keys==m){ cout<<n1.d<<endl; save=true; break; }
 53         
 54             for(int i=0;i<4;i++){
 55                 int x = n1.r + dx[i];
 56                 int y = n1.c + dy[i];
 57                 if( x>=1 && x<=n && y>=1 && y<=n && maze[x][y]!='#' ){
 58                     if( maze[x][y]=='S' ) {//遇到蛇
 59                         int kill = n1.kill;
 60                         //看这个守卫有没有被杀死
 61                         if( kill & (1<<(snakeID[x][y]-1) ) ){//守卫被杀死 
 62                             if( !vis[x][y][n1.keys][kill] ) {
 63                                 vis[x][y][n1.keys][kill]=1;
 64                                 q.push( node(x,y,n1.keys,kill,n1.d+1) );
 65                             }
 66                         }
 67                         else{//守卫还活着 
 68                             if( !vis[x][y][n1.keys][kill+(1<<(snakeID[x][y]-1)) ] ){
 69                                 vis[x][y][n1.keys][kill+(1<<(snakeID[x][y]-1)) ]=1;
 70                                 q.push( node(x,y,n1.keys,kill+(1<<(snakeID[x][y]-1)),n1.d+2) );
 71                             }
 72                         }
 73                     }
 74                     else if(maze[x][y]=='K' || maze[x][y]=='T' ||  maze[x][y]=='.' ){//这三种情况一种处理方式 
 75                         if( !vis[x][y][n1.keys][n1.kill] ){
 76                             vis[x][y][n1.keys][n1.kill]=1;
 77                             q.push( node(x,y,n1.keys,n1.kill,n1.d+1) );
 78                         }
 79                     }
 80                     else /*数字*/{
 81                         //看可不可以拿
 82                         int key = int(maze[x][y])-48;
 83                         if( n1.keys>=key || n1.keys!=key-1 ){//拿过了或拿不了 
 84                             if( !vis[x][y][n1.keys][n1.kill] ){
 85                                 vis[x][y][n1.keys][n1.kill]=1;
 86                                 q.push( node(x,y,n1.keys,n1.kill,n1.d+1) );
 87                             }
 88                         }
 89                         else{//可以拿 
 90                             if( !vis[x][y][key][n1.kill] ){
 91                                 vis[x][y][key][n1.kill]=1;
 92                                 q.push( node(x,y,key,n1.kill,n1.d+1) );
 93                             }
 94                         }
 95                     }
 96                 }
 97             }
 98         }
 99         if(!save) cout<<"impossible"<<endl;
100         while(!q.empty()) q.pop();                            
101     }
102     
103     return 0;
104 }

记得用priority_queue的时候如果往里面放node,自己重载小于号的形式是在struct里写:

【记得要写const】

bool operator < (const node n2) const{
  // return  .....
}
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9374974.html