hdu 5025 bfs+状态压缩

点击打开链接

#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;
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值