BFS搜索。每分钟走一格,且在魔王回来前逃到大门处算作逃跑成功,即从起点到终点的最少步数小于t即可。即使是等于t,也是失败的。在迷宫中求起点到终点的最少步数,很容易便想到BFS。而此题中,想要通过门,必须要有对应的钥匙,所以是有可能为了取钥匙开门,而在一个格子上走过好几次。因此,写标记格子是否走过的vis数组时,可以认为通过同一个格子时如果携带的钥匙不同,可以认为是不同的通过方式。因此,可以将vis数组设为三维数组,前两维表示格子,第三维通过位运算来表示携带钥匙的情况。最多有十柄钥匙,因此携带钥匙的情况最多有2^10=1024种。
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
struct Node
{
int x,y,t,key;
};
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int vis[21][21][1025];
int map[21][21];
int n,m,t;
int bfs(int sti,int stj)
{
struct Node start,order,next;
queue<Node> q;
start.x=sti;
start.y=stj;
start.t=0;
start.key=0;
vis[sti][stj][0]=1;
q.push(start);
while(!q.empty())
{
order=q.front();
q.pop();
for(int i=0;i<4;i++)
{
next=order;
next.x+=dir[i][0];
next.y+=dir[i][1];
next.t++;
if(next.t>=t)
continue;
if(next.x<0||next.x>=n||next.y<0||next.y>=m)
continue;
if(vis[next.x][next.y][next.key])
continue;
if(map[next.x][next.y]=='^')
return next.t;
else if(map[next.x][next.y]=='*')
continue;
/*
map[next.x][next.y]-'A'+1为用钥匙对应的第三维数据的位数;
next.key>> (map[next.x][next.y]-'A')指的是将key右移一定的位数(不改变key值),
使得第一位恰好对应该门所需的钥匙
数字1转化为二进制的话,只有第一位为1,其他位皆为0。与数字1进行&运算,即可判断一个数第一位是否为1
*/
else if (map[next.x][next.y]>='A'&&map[next.x][next.y]<='Z')
{
if(next.key>> (map[next.x][next.y]-'A') &1)
{
vis[next.x][next.y][next.key]=1;
q.push(next);
}
}
else if (map[next.x][next.y]>='a'&&map[next.x][next.y]<='z')
{
next.key=next.key|( 1<< (map[next.x][next.y]-'A') );
//将key的表示当前格子上钥匙的那一位改为1
vis[next.x][next.y][next.key]=1;
q.push(next);
}
else
{
vis[next.x][next.y][next.key]=1;
q.push(next);
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&t)==3)
{
int sti=0,stj=0;
char w=getchar();
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
w=getchar();
map[i][j]=w;
if(w=='@')
{
sti=i,stj=j;
}
}
getchar();
}
int ans=bfs(sti,stj);
printf("%d\n",ans);
}
return 0;
}