hdu1885 Key Task

刚开始看到这题都吓到了,第一感觉就是不能记录已走过的点,一旦记录了,那假设钥匙在对面,门在这边,那拿完钥匙就回不来了;

可是,如果不记录的话,那岂不是在整个地图了乱窜,绝对超时,甚至是死循环;

之后,想了想,把每个点在入队列的时候,记录下状态每一个点的状态,即又有没有拿到钥匙,拿到哪几种钥匙之类的,如果回溯时,俩点的状态一样,则没必要入队,这确实是一种可行的办法,可是想到这里,突然,想到,要对每一个点保存16种状态,那内存肯定要爆了呀,结果思路就这么停了,想不出别的办法了……

查了一下,原来记录状态是用位运算保存呀,郁闷呐,亏我知道这东西存在,亏我还用过位运算保存过一个数字是否出现过,结果我居然一点都没想到,惭愧呀

是这样保存的,开一个三维的数组,flag[101][101][16],记录每一个点的状态,除了坐标之外,保存的是一个点有没有钥匙,有多少把钥匙,每一个位保存一把钥匙的状态,总共十六种状态

假设 // b,y,r, g 钥匙分别用二进制的第一,二,三,四位保存,flag&1 ==1 表示 该状态b钥匙已经有了,当拿到b钥匙时,flag|=1,记录下来。

#include<iostream>
#include<queue>
using namespace std;
char map[101][101];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}},n,m;
int flag[101][101][16];
// b,y,r, g: 1,2,4,8
struct node
{
	int x,y,cnt,v;
	node(int _x=0,int _y=0,int _cnt=0 ,int _v=0):x(_x),y(_y),cnt(_cnt),v(_v){};
	friend bool operator <(const node &a,const node &b)
	{
		return a.cnt>b.cnt;
	}
};
node f;
bool OK(int i,int j,int va)
{
	if(map[i][j]=='B'&&(va&1))
		return true;
	if(map[i][j]=='Y'&&(va&2))
		return true;
	if(map[i][j]=='R'&&(va&4))
		return true;
	if(map[i][j]=='G'&&(va&8))
		return true;
	return false;
}
int bfs()
{
	flag[f.x][f.y][f.v]=1;
	priority_queue<node> Q;
	Q.push(f);
	while(!Q.empty())
	{
		node t=Q.top();
		Q.pop();
		for(int k=0;k<4;k++)
		{
			int i=t.x+dir[k][0];
			int j=t.y+dir[k][1];
			if(i<n&&i>=0&&j<m&&j>=0&&map[i][j]!='#')
			{
				if(OK(i,j,t.v)&&!flag[i][j][t.v])
				{
					flag[i][j][t.v]=1;
					Q.push(node(i,j,t.cnt+1,t.v));
				}
				else if(map[i][j]=='b'&&!flag[i][j][t.v|1])
				{
					flag[i][j][t.v|1]=1;
					Q.push(node(i,j,t.cnt+1,t.v|1));
				}
				else if(map[i][j]=='y'&&!flag[i][j][t.v|2])
				{
					flag[i][j][t.v|2]=1;
					Q.push(node(i,j,t.cnt+1,t.v|2));
				}
				else if(map[i][j]=='r'&&!flag[i][j][t.v|4])
				{
					flag[i][j][t.v|4]=1;
					Q.push(node(i,j,t.cnt+1,t.v|4));
				}
				else if(map[i][j]=='g'&&!flag[i][j][t.v|8])
				{
					flag[i][j][t.v|8]=1;
					Q.push(node(i,j,t.cnt+1,t.v|8));
				}
				else if(map[i][j]=='.'&&!flag[i][j][t.v])
				{
					flag[i][j][t.v]=1;
					Q.push(node(i,j,t.cnt+1,t.v));
				}
				else if(map[i][j]=='X')
					return t.cnt+1;
			}
		}
	}
		return 0;
}
int main()
{
	while(cin>>n>>m&&(n||m))
	{
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='*')
					f.x=i,f.y=j;
			}
		f.cnt=0;f.v=0;map[f.x][f.y]='.';
		memset(flag,0,sizeof(flag));
		int t=bfs();
		if(t)
		cout<<"Escape possible in "<<t<<" steps."<<endl;
		else cout<<"The poor student is trapped!"<<endl;
	}
	return 0;
}
posted @ 2011-08-05 11:37  枕边梦  阅读(1093)  评论(0编辑  收藏  举报