题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429
用二进制每一位表示是否拿到某个门的钥匙,记录状态
若第二次走到同一位置,判断若状态不变则不再继续入队
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
struct node{
int x,y;
int step;
int stu;
};
int n,m,t;
char map[30][30];
int vis[30][30][2000];
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
queue<node> q;
int sx,sy,ex,ey;
bool jud(node next){
int x=next.x,y=next.y;
if(x<0||x>=n||y<0||y>=m)
return false;
if(map[x][y]=='*')
return false;
if(vis[x][y][next.stu])
return false;
if(map[x][y]>='A'&&map[x][y]<='J'&&(next.stu&(1<<(map[x][y]-'A')))==0)
return false;
if(next.step>=t)
return false;
return true;
}
int bfs(){
while(!q.empty())q.pop();
memset(vis,0,sizeof(vis));
node now,next;
int i,j;
now.x=sx,now.y=sy;
now.step=0;
now.stu=0;
q.push(now);
while(!q.empty()){
now=q.front();
q.pop();
for(i=0;i<4;++i){
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
next.step=now.step+1;
next.stu=now.stu;
if(!jud(next))continue;
int nx=next.x,ny=next.y;
if(map[nx][ny]>='a'&&map[nx][ny]<='j'){
next.stu=next.stu|(1<<(map[nx][ny]-'a'));
}
if(nx==ex&&ny==ey){
return next.step;
}
vis[nx][ny][next.stu]=1;
q.push(next);
}
}
return -1;
}
int main(){
int i,j;
int ans;
while(scanf("%d%d%d",&n,&m,&t)!=EOF){
for(i=0;i<n;++i){
scanf("%s",map[i]);
for(j=0;j<m;++j){
if(map[i][j]=='@'){
sx=i,sy=j;
map[i][j]='.';
}
if(map[i][j]=='^'){
ex=i,ey=j;
}
}
}
ans=bfs();
printf("%d\n",ans);
}
return 0;
}