• 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  .....
    }
  • 相关阅读:
    完了!生产事故!几百万消息在消息队列里积压了几个小时!
    crontab详解
    系统架构中为什么要引入消息中间件
    Linux常用命令
    什么是JWT(JSON WEB TOKEN)
    API接口安全性设计
    MySQLDump在使用之前一定要想到的事情
    api接口安全以及https
    shell study
    linux中注册系统服务—service命令的原理通俗
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9374974.html
Copyright © 2020-2023  润新知