题意:孙悟空要去救唐僧,有M个钥匙,只有拿到了第k种钥匙才能拿第k+1种钥匙,必须拿到所有钥匙才能救人。迷宫里面有蛇,杀死一条蛇要花费两秒。求救唐僧需要的最少时间。
思路:记录下当前拿到的钥匙数量,蛇最多五条,用状态压缩记录杀死蛇的状态
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct pos
{
int x,y,k,s;
pos(){}
pos(int x,int y,int k,int s):x(x),y(y),k(k),s(s){}
};
int n,m;
int dp[105][105][10][1<<5];
int dir[4][2]={-1,0,0,1,1,0,0,-1};
int snack[105][105];
char matrix[105][105];
void bfs(pos start)
{
queue<pos> q;
q.push(start);
while(!q.empty())
{
pos tt=q.front();
q.pop();
// cout<<tt.x<<' '<<tt.y<<' '<<tt.k<<endl;
for(int d=0;d<4;++d)
{
int ii=tt.x+dir[d][0];
int jj=tt.y+dir[d][1];
if(ii<0||ii>=n||jj<0||jj>=n)continue;
if(matrix[ii][jj]=='#')continue;
int kk=tt.k;
int ss=tt.s;
if(matrix[ii][jj]-'0'==tt.k+1)kk++;
if(matrix[ii][jj]=='S')
{
ss|=1<<snack[ii][jj];
}
int add=ss==tt.s?1:2;
if(dp[ii][jj][kk][ss]==-1||dp[ii][jj][kk][ss]>dp[tt.x][tt.y][tt.k][tt.s]+add)
{
dp[ii][jj][kk][ss]=dp[tt.x][tt.y][tt.k][tt.s]+add;
q.push(pos(ii,jj,kk,ss));
}
}
}
}
int main()
{
// freopen("data.txt","r",stdin);
while(scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
memset(dp,-1,sizeof(dp));
int totsn=0;
pos start;
pos Tang;
for(int i=0;i<n;++i)
{
scanf("%s",matrix[i]);
for(int j=0;j<n;++j)
{
if(matrix[i][j]=='K'){start.x=i;start.y=j;start.k=0;start.s=0;}
else if(matrix[i][j]=='S'){snack[i][j]=totsn++;}
else if(matrix[i][j]=='T'){Tang.x=i;Tang.y=j;}
}
}
dp[start.x][start.y][0][0]=0;
bfs(start);
int ans=-1;
for(int i=0;i<=(1<<totsn)-1;++i)
{
if(dp[Tang.x][Tang.y][m][i]==-1)continue;
if(ans==-1)ans=dp[Tang.x][Tang.y][m][i];
else ans=min(ans,dp[Tang.x][Tang.y][m][i]);
}
if(ans==-1)printf("impossible\n");
else printf("%d\n",ans);
}
return 0;
}