hdu5025 Saving Tang Monk 状压bfs

20 篇文章 0 订阅

传送门: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;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值