hdu 5025 Saving Tang Monk 2014 ACM/ICPC Asia Regional Guangzhou Online bfs

9 篇文章 0 订阅

题目链接:hdu 5025

        给出一张图,K表示起点位置,T表示终点位置,S表示有蛇的房间,走过带蛇的房间的时候需要额外的一点时间,数字表示钥匙,#表示不可达,'.'表示普通路,要到终点时必须拿到第k把钥匙。

        拿钥匙的规则,要拿第n把钥匙,需要首先拿到第n-1把钥匙。


        bfs,需要记录每个点的时间t,已经拿到的钥匙v,二进制保存已经杀过的蛇,然后用宽搜找出最优解

        vis[x][y][v][s] 表示点(x,y)拿到钥匙v,杀过蛇的状态s是否访问过来标记访问状态

/******************************************************
 * File Name:   1004.cpp
 * Author:      kojimai
 * Creater Time:2014年09月20日 星期六 13时31分59秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
#define FFF 105
char s[FFF][FFF];
bool vis[105][105][10][32];
int move[4][2]={
	-1,0,1,0,0,1,0,-1
};
struct node 
{
	int x,y,t,v,snake;
	bool operator < (const node &a) const{
		return t>a.t;
	}
};
priority_queue<node> p;
int main()
{
	int n,k,sx,sy,ex,ey;
	while(scanf("%d%d",&n,&k),n+k)
	{
		memset(vis,false,sizeof(vis));
		while(!p.empty())
		{
			p.pop();
		}
		int nw=0;
		for(int i=0;i<n;i++)
		{
			scanf("%s",s[i]);
			for(int j=0;j<n;j++)
			{
				if(s[i][j]=='K')
				{
					sx=i;
					sy=j;
				}
				else if(s[i][j]=='T')
				{
					ex=i;
					ey=j;
				}
				else if(s[i][j]=='S')
				{
					s[i][j]='a'+nw++;
				}
			}
		}
		node now;
		now.x=sx;now.y=sy;now.t=0;now.v=0;now.snake=0;
		p.push(now);
		vis[now.x][now.y][0][0]=true;
		int ans=-1;
		node tmp;
		while(!p.empty())
		{
			if(ans!=-1)
				break;
			now=p.top();p.pop();
			//cout<<"x="<<now.x<<" y="<<now.y<<" t="<<now.t<<" v="<<now.v<<" snake="<<now.snake<<endl;
			int xx,yy;
			for(int i=0;i<4;i++)
			{
				xx=now.x+move[i][0];yy=now.y+move[i][1];
				tmp.x=xx;tmp.y=yy;tmp.t=now.t+1;tmp.v=now.v;tmp.snake=now.snake;
				if(xx<0||xx>=n||yy<0||yy>=n||s[xx][yy]=='#')
					continue;
				if(s[xx][yy]=='T')//t
				{
					if(now.v==k)
					{
						ans=now.t+1;
						break;
					}
				}
				else if(s[xx][yy]>='1'&&s[xx][yy]<='0'+k)//key
				{
					if(now.v+1==s[xx][yy]-'0')
					{
						tmp.v=now.v+1;
					}
				}
				else if(s[xx][yy]>='a'&&s[xx][yy]<'a'+nw)//snake
				{
					int sna=s[xx][yy]-'a';
					if(!(now.snake&(1<<sna)))
					{
						tmp.t=now.t+2;
						tmp.snake|=(1<<sna);
					}
				}
				if(!vis[xx][yy][tmp.v][tmp.snake])
				{
				//cout<<" tmp x="<<tmp.x<<" y="<<tmp.y<<" t="<<tmp.t<<" v="<<tmp.v<<" snake="<<tmp.snake<<endl;
					vis[xx][yy][tmp.v][tmp.snake]=true;
					p.push(tmp);
				}
			}
		}
		if(ans==-1)
			printf("impossible\n");
		else
			printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值