题意:类似走迷宫的一个题,给一个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;
}