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 ..... }