题意:类似走迷宫的一个题,给一个n*n的地图,从K开始走到T,标#号的地方不能走。走的过程中,要按顺序拿m种钥匙(在地图中是数字,每种可能有多把),如果遇到蛇S,需要花1的额外时间把它打死。输出走到终点的最短时间。
思路:状态空间搜索。如果把钥匙的取得情况和蛇的生存情况也看成状态,就简单多了。状态第一、二维是行和列。钥匙最多9,需要按顺序拿,所以第三维开10就足够了。蛇的生存情况可以用5位二进制表示,也就是第四维开32。然后用优先队列搜。比赛的时候这题A出来真是扬眉吐气~
#include <iostream> #include <stdio.h> #include <cmath> #include <algorithm> #include <iomanip> #include <cstdlib> #include <string> #include <string.h> #include <vector> #include <queue> #include <stack> #include <map> #include <assert.h> #include <set> #include <ctype.h> #define ll long long #define max3(a,b,c) max(a,max(b,c)) using namespace std; char mp[110][110]; int a[110][110][10][32]; int dn[]={-1,1,0,0}; int dm[]={0,0,-1,1}; struct node{ int nn; int mm; int key; int snk; int dis; node(int a,int b,int c,int d,int ee){ nn=a; mm=b; key=c; snk=d; dis=ee; } bool operator<(node b)const{ return dis>b.dis; } }; int main(){ int n,m; while(cin>>n>>m){ if(n==0&&m==0)break; memset(a,-1,sizeof(a)); int snk=0; int startn; int startm; int endn; int endm; for(int i=1;i<=n;i++){ scanf("%s",mp[i]+1); for(int j=1;j<=n;j++){ if(mp[i][j]=='K'){ startn=i; startm=j; }else if(mp[i][j]=='S'){ mp[i][j]=snk+'A'; snk++; }else if(mp[i][j]=='T'){ endn=i; endm=j; } } } node start(startn,startm,0,0,0); a[startn][startm][0][0]=0; priority_queue<node> que; que.push(start); int ans=0; while(!que.empty()){ node cur=que.top(); que.pop(); int cn=cur.nn; int cm=cur.mm; int ckey=cur.key; int csnk=cur.snk; int cdis=cur.dis; if(cn==endn&&cm==endm&&ckey==m){ ans=cdis; break; } for(int d=0;d<4;d++){ int newn=cn+dn[d]; int newm=cm+dm[d]; if( newn<1||newn>n||newm<1||newm>n )continue; if( mp[newn][newm]=='#' )continue; if( mp[newn][newm]=='.'||mp[newn][newm]=='T'||mp[newn][newm]=='K' ){ if(a[newn][newm][ckey][csnk]==-1){ a[newn][newm][ckey][csnk]=cdis+1; node nd(newn,newm,ckey,csnk,cdis+1); que.push(nd); } } if( mp[newn][newm]>='A'&&mp[newn][newm]<='E' ){ int tmp=mp[newn][newm]-'A'; tmp=(1<<tmp); if(tmp&csnk){ if(a[newn][newm][ckey][csnk]==-1){ a[newn][newm][ckey][csnk]=cdis+1; node nd(newn,newm,ckey,csnk,cdis+1); que.push(nd); } }else{ if(a[newn][newm][ckey][csnk|tmp]==-1){ a[newn][newm][ckey][csnk|tmp]=cdis+2; node nd(newn,newm,ckey,csnk|tmp,cdis+2); que.push(nd); } } } if( mp[newn][newm]>='1'&&mp[newn][newm]<='9' ){ int tmp=mp[newn][newm]-'0'; if(tmp==ckey+1){ if(a[newn][newm][ckey+1][csnk]==-1){ a[newn][newm][ckey+1][csnk]=cdis+1; node nd(newn,newm,ckey+1,csnk,cdis+1); que.push(nd); } }else{ if(a[newn][newm][ckey][csnk]==-1){ a[newn][newm][ckey][csnk]=cdis+1; node nd(newn,newm,ckey,csnk,cdis+1); que.push(nd); } } } } } if(ans==0){ cout<<"impossible"<<endl; }else{ cout<<ans<<endl; } } return 0; }