题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1429
题意:迷宫的加强版,迷宫里有钥匙和门,问在指定的时间下能否逃出
题解:用二进制位来记录是否有该门的钥匙,然后上BFS
#include<cstdio>
#include<queue>
#include<cstring>
#define FFC(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n,m,t,j,sx,sy,d[][2]={1,0,-1,0,0,1,0,-1};bool v[22][22][1025];char g[22][22];
struct dt{int x,y,tm,key;};//用二进制位来压缩状态
bool check(int x,int y){if(x<1||x>n||y<1||y>m||g[x][y]=='*')return 0;return 1;}
int fuck(){
dt s,o;s.x=sx,s.y=sy,s.tm=0,s.key=0;
memset(v,0,sizeof(v));
queue<dt>Q;Q.push(s);
while(!Q.empty()){
o=Q.front();Q.pop();
if(g[o.x][o.y]=='^'&&o.tm<t)return o.tm;
if(o.tm>t)continue;
for(int i=0;i<4;i++){
int xx=o.x+d[i][0],yy=o.y+d[i][1],kkey=o.key;
if(!check(xx,yy))continue;//检测边界
if(g[o.x][o.y]>='A'&&g[o.x][o.y]<='Z'&&!((o.key>>(g[o.x][o.y]-'A'))&1))continue;//检测能否打开门
if(g[xx][yy]>='a'&&g[xx][yy]<='z')kkey|=(1<<(g[xx][yy]-'a'));//拣钥匙
if(v[xx][yy][kkey])continue;//判断在有这些钥匙的情况下是否搜过该点
s.x=xx,s.y=yy,s.tm=o.tm+1,s.key=kkey,v[xx][yy][kkey]=1;
Q.push(s);
}
}
return -1;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&t)){
FFC(i,1,n){
getchar();
for(j=1;j<=m;j++){scanf("%c",&g[i][j]);if(g[i][j]=='@')sx=i,sy=j;}
}
printf("%d\n",fuck());
}
return 0;
}