题目连接: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[][]={,,-,,,,,-};bool v[][][];char g[][];
struct dt{int x,y,tm,key;};//用二进制位来压缩状态
bool check(int x,int y){if(x<||x>n||y<||y>m||g[x][y]=='*')return ;return ;}
int fuck(){
dt s,o;s.x=sx,s.y=sy,s.tm=,s.key=;
memset(v,,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=;i<;i++){
int xx=o.x+d[i][],yy=o.y+d[i][],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'))&))continue;//检测能否打开门
if(g[xx][yy]>='a'&&g[xx][yy]<='z')kkey|=(<<(g[xx][yy]-'a'));//拣钥匙
if(v[xx][yy][kkey])continue;//判断在有这些钥匙的情况下是否搜过该点
s.x=xx,s.y=yy,s.tm=o.tm+,s.key=kkey,v[xx][yy][kkey]=;
Q.push(s);
}
}
return -;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&t)){
FFC(i,,n){
getchar();
for(j=;j<=m;j++){scanf("%c",&g[i][j]);if(g[i][j]=='@')sx=i,sy=j;}
}
printf("%d\n",fuck());
}
return ;
}