传送门:hdu5025
题意:悟空要去救师傅,必须按顺序拿到规定数目的钥匙,遇到蛇(S)要多花一秒钟,问最短时间。
自己不不知道怎么判定蛇死没死,看题解发现新大陆,用一个数组来进行状态压缩,book[i][j][k][s]标记i,j点收集钥匙的状态(k)和杀死蛇的状态(s),其中最后一维最为神奇,因为一共最多五条蛇,所以给蛇编号以后用五位二进制数来保存五条蛇的状态,1表示已经被杀死了,0表示尚未被杀死。
看了题解才发现世界真奇妙啊。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int go[4][2]={0,1,1,0,0,-1,-1,0};
int n,m,book[105][105][10][35];//注意这里最后一维因为要表示5位2进制数,所以最小为33.
int er,ec,sr,sc;
int cnt,ans;
char map[105][105];
struct node{
int r,c,k,s,t;
};
queue<node>q;
int bfs()
{
ans=inf;
while(!q.empty())
q.pop();
q.push((node){sr,sc,0,0,0});
while(!q.empty())
{
node a=q.front();
q.pop();
int r=a.r,c=a.c,k=a.k,t=a.t;
if(k==m&&r==er&&c==ec)
{
ans=min(ans,t);
}
if(book[r][c][k][a.s]!=-1)
continue;
book[r][c][k][a.s]=t;
for(int i=0;i<4;i++)
{
int nr=r+go[i][0],nc=c+go[i][1];
int s=map[nr][nc]-'A';
if(0<=s&&s<cnt)
{
if((1<<s)&a.s)//判断蛇死没死的关键语句,可以自己在纸上举个例子试试
{
q.push((node){nr,nc,k,a.s,t+1});
}
else
q.push((node){nr,nc,k,(1<<s)|a.s,t+2});
}
else if(map[nr][nc]-'0'==k+1)//判断是不是下一把要拿的钥匙
{
q.push((node){nr,nc,k+1,a.s,t+1});
}
else if(('1'<=map[nr][nc]&&map[nr][nc]<m+'1')||map[nr][nc]=='K'||map[nr][nc]=='T'||map[nr][nc]=='.')
q.push((node){nr,nc,k,a.s,t+1});
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)&&n+m)
{
getchar();
cnt=0;
memset(book,-1,sizeof(book));
memset(map,0,sizeof(map));
for(int i=0;i<n;i++)
{
gets(map[i]);
for(int j=0;j<n;j++)
{
if(map[i][j]=='K')
{
sr=i;
sc=j;
}
if(map[i][j]=='T')
{
er=i;
ec=j;
}
if(map[i][j]=='S')//给蛇编号
{
map[i][j]='A'+cnt;
cnt++;
}
}
}
bfs();
if(ans==inf)
printf("impossible\n");
else
printf("%d\n",ans);
}
return 0;
}