hdu1429广搜+状态压缩(二进制)

广搜的全称为广度优先搜索,会用到队列
结构中增加char类型的key[26],会MLE(超内存);所以用二进制来表示手头的钥匙
100表示有第3把,111表示有第3,2,1把钥匙,如果该点为钥匙点,则可采用|运算来模拟拾取,
显然0001|1000 = 1001,同理,当为相应的门时采用&运算来模拟开启,
例如1101 & 0001 = 0001(即可以打开'A'门)

#include<stdio.h>
#include<queue>
using namespace std;//定义队列一定要写这个 
int n,m,t;
char map[21][21];
int hash[21][21][1025];//2的10为1024 
int dx[9]={0,0,-1,1};
int dy[9]={-1,1,0,0};
struct state
{
	int x;int y;int key;int st;
	int logic()
	{
		if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='*') return 1;
		else return 0;
	}
}cur,next,start;
queue<state>q;//建立以state这个数据类型为节点的队列,队列的变量为q;
int bfs()
{
	while(!q.empty())
	{
		cur=q.front();//front 返回队首指针
		q.pop();//pop 弹栈,删除栈顶元素
		if(map[cur.x][cur.y]=='^') 
		{  
		  if(cur.st<t)
		  return cur.st;
		}
		if(cur.st>=t) break;
		for(int i=0;i<4;i++)
		{
			next=cur;
			next.x+=dx[i];
			next.y+=dy[i];
			next.st++;
			if(next.logic())
			{
				 if(map[next.x][next.y]>='A'&&map[next.x][next.y]<='J')
				 {
				 	 int key=(map[next.x][next.y]-'A');
					  //例map[][]为'b',key=1;
				 	 if(((next.key>>key)&1)&&!hash[next.x][next.y][next.key]) 
				 	 {  //>>右移运算符 ,若next=1010,右移一位变为101,
					    //101&1!=0即可以开门 
				 	 	hash[next.x][next.y][next.key]=1;
				 	 	q.push(next);
				 	 }
				 }
				 else if(map[next.x][next.y]>='a'&&map[next.x][next.y]<='j')
				 {
				 	 int key=(1<<(map[next.x][next.y]-'a'));
				 	 //<<左移运算符 ,例map[][]为'b',则左移1位,变10 
			         next.key=(next.key|key);//把key放进去,
              //例next.key=1001, next.key|key=1001|10=1010就把第二把钥匙放进去了 
		             if(!hash[next.x][next.y][next.key])
		             {   
		                 hash[next.x][next.y][next.key]=1;
		             	 q.push(next);
		             }
				 }
				 else 
				 {
				 	  if(!hash[next.x][next.y][next.key])
		             {   
		                 hash[next.x][next.y][next.key]=1;
		             	 q.push(next);
		             }
				 }
			}
		}
	}
	return -1;
} 
int main()
{
	while(scanf("%d%d%d",&n,&m,&t)!=EOF)
	{    
	    memset(hash,0,sizeof(hash));
		for(int i=0;i<n;i++)
		{    
			scanf("%s",&map[i]);
			for(int j=0;j<m;j++)
			{
				if(map[i][j]=='@') start.x=i,start.y=j;
			}
		}
			start.key=0;start.st=0;
			while(!q.empty()) q.pop();
			hash[start.x][start.y][start.key]=1;//相同的状态就不重复走了 
			q.push(start);
			printf("%d\n",bfs());
		
	}
}

 

posted @ 2013-04-14 15:10  宛如  阅读(143)  评论(0编辑  收藏  举报