#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int M=110;
int n,m,ans;
char g[M][M];
int snum,snake[M][M];// 记录snake的位置
int sx,sy;
int vis[M][M][15][1<<6];//vis[x][y][key][snake] 同一点只要杀的snake不同 or key不同就可以重复走 所以开4维vis
struct point{
int x,y;
int key;
int snake;
int step;
bool operator<(point a)const{
return step>a.step;
}
}s,s1,s2;
struct Offset{
int x,y;
}offset[4]={{-1,0},{1,0},{0,-1},{0,1}};
priority_queue<point> q; //snake的位置有权值 则用优先队列,保证按路径递增
void bfs()
{
s.x=sx;
s.y=sy;
s.step=0;
s.snake=0;
s.key=0;
q.push(s);
vis[sx][sy][0][0]=1;
while(!q.empty())
{
s1=q.top();
q.pop();
for(int i=0;i<4;i++)
{
s2.x=s1.x+offset[i].x;
s2.y=s1.y+offset[i].y;
s2.snake=s1.snake;
s2.step=s1.step+1;
s2.key=s1.key;
if(s2.x>=0&&s2.x<n&&s2.y>=0&&s2.y<n&&g[s2.x][s2.y]!='#'&&vis[s2.x][s2.y][s2.key][s2.snake]==0)
{
vis[s2.x][s2.y][s2.key][s2.snake]=1;
if(g[s2.x][s2.y]==s1.key+'0'+1)//只有num之前的钥匙 才能拿
{
s2.key+=1;
q.push(s2);
}
else if(g[s2.x][s2.y]=='S')
{
if(!(s2.snake&(1<<snake[s2.x][s2.y])))// 位运算:01001表示杀了 1号和4好蛇 相&就能判断该蛇当前杀没杀
{
s2.snake|=(1<<snake[s2.x][s2.y]);
s2.step+=1;
}
q.push(s2);
}
else if(g[s2.x][s2.y]=='T'&&s2.key==m)
{
ans=s2.step;
return;
}
else
{
q.push(s2);
}
}
}
}
}
int main()
{
while(cin>>n>>m&&(n+m))
{
ans=-1;
snum=0;
while(!q.empty())
{
q.pop();
}
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>g[i][j];
if(g[i][j]=='K')
{
sx=i;
sy=j;
}
if(g[i][j]=='S')
{
snake[i][j]=snum++;//给snake编号
}
}
}
bfs();
if(ans==-1)
cout<<"impossible"<<endl;
else
cout<<ans<<endl;
}
return 0;
}
hdu 5025 bfs+状态压缩
最新推荐文章于 2020-08-28 22:24:59 发布