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());
}
}

浙公网安备 33010602011771号