【题意】求悟空到师傅的最短距离,这中途会有一些门,悟空必须依次拿到钥匙,打开所有的门,中途遇到妖怪就会多停留1s,求悟空救出师傅的最短时间!
【解题思路】我的第一道dfs+状压!其中dp[x][y][k][s]中,x,y代表位置,k代表拿到了k把钥匙,s代表状态。
【AC代码】
using namespace std;
const int maxn = 102;
const int inf = 0x3f3f3f3f;
struct node{
int x,y,k,s,d;
node(){}
node(int x,int y,int k,int s,int d):x(x),y(y),k(k),s(s),d(d){}
};
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int dp[maxn][maxn][10][32];
char maze[maxn][maxn];
int n,m,sx,sy,cnt;
int bfs(int sx,int sy)
{
queue<node>que;
int ans = inf;
que.push(node(sx,sy,0,0,0));
while(!que.empty())
{
node cur = que.front();
que.pop();
int x=cur.x,y=cur.y,k=cur.k,s=cur.s;
if(k==m&&maze[x][y]=='T')
{
ans = min(ans,cur.d);
}
if(dp[x][y][k][s]!=-1)continue;
dp[x][y][k][s]=cur.d;
for(int i=0;i<4;i++)
{
int dx=x+dir[i][0];
int dy=y+dir[i][1];
int st = maze[dx][dy]-'A';
if(st>=0&&st<cnt)//杀蛇
{
if(s&(1<<st)) que.push(node(dx,dy,k,s,cur.d+1));
else que.push(node(dx,dy,k,s^(1<<st),cur.d+2));
}
else//拿钥匙
{
if(maze[dx][dy]=='1'+k)
{
que.push(node(dx,dy,k+1,s,cur.d+1));
}
else if((maze[dx][dy]>='1'&&maze[dx][dy]<'1'+m)||(maze[dx][dy]=='.'||maze[dx][dy]=='K'||maze[dx][dy]=='T'))
{
que.push(node(dx,dy,k,s,cur.d+1));
}
}
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cnt = 0;
if(n==0&&m==0)return 0;
memset(dp,-1,sizeof(dp));
memset(maze,0,sizeof(maze));
for(int i=1; i<=n; i++)
{
scanf("%s",maze[i]+1);
for(int j=1; j<=n; j++)
{
if(maze[i][j]=='S')
{
maze[i][j] = 'A'+cnt;
cnt++;
}
if(maze[i][j]=='K')
{
sx=i,sy=j;
}
}
}
// for(int i=1; i<=n; i++)
// {
// for(int j=1; j<=n; j++)
// {
// printf("%c",maze[i][j]);
// }
// printf("\n");
// }
int ans = bfs(sx,sy);
if(ans==inf)
{
puts("impossible");
}
else
{
printf("%d\n",ans);
}
}
return 0;
}