地址:
点击打开链接
这个题目有几个很坑的地方,首先是我们需要开多一维,记录带钥匙走每一个块,和不带钥匙走是不一样的,所以我们多记录了一个。另外,不只是"."能走,“@”也能走。另外,每个状态查看vis的时候,需要查看走到这一状态时的状态,因此这个时候key的携带数量也会更新(但是要注意,不是啥都更新,拿到钥匙的时候,更新一下,看看vis是不是有过,但是没有说开门消耗钥匙,这个很关键),最后一个点,明明给了20*20最大的迷宫,但却要开到50*50才能过,哎,神坑啊。
代码如下:
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std ;
char Map[50][50];
int t ,m , n,sx,sy;
int vis[50][50][2000];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct Node{
int x ,y,step ;
int key ;
bool check()
{
if(x>=0&&x<m&&y>=0&&y<n)
return true ;
return false ;
}
};
int bfs(){
Node a ,temp;
a.x =sx ;a.key = 0;
a.y =sy;
a.step=0;
queue<Node> que ;
que.push(a);
vis[sx][sy][0]=1;
while(!que.empty())
{
a = que.front();
que.pop();
// cout << "a : "<<a.x <<" " << a.y <<endl;
if(a.step>=t)
return -1 ;
if(Map[a.x][a.y]=='^')
return a.step ;
for(int i = 0 ; i < 4 ; i ++)
{
temp = a ;
temp.x+=dir[i][0];
temp.y+=dir[i][1];
temp.step++;
if(temp.check()&&Map[temp.x][temp.y]!='*')
{
//cout << temp.x <<" " << temp.y <<" " << temp.key<<endl;
if(Map[temp.x][temp.y]>='a'&&Map[temp.x][temp.y]<='z')
{
int tt= temp.key|(1<<(Map[temp.x][temp.y]-'a'));
if( !vis[temp.x][temp.y][tt])
{
temp.key =tt ;
vis[temp.x][temp.y][temp.key] =1;
que.push(temp);
}
}else if(Map[temp.x][temp.y]>='A'&&Map[temp.x][temp.y]<='Z')
{
int kt= temp.key&(1<<(Map[temp.x][temp.y]-'A'));
if(kt>0&&!vis[temp.x][temp.y][temp.key])
{
vis[temp.x][temp.y][temp.key] =1;
que.push(temp);
}
}else
{
if(!vis[temp.x][temp.y][temp.key])
{
vis[temp.x][temp.y][temp.key] =1;
que.push(temp);
}
}
}
}
}
return -1;
}
int main(){
int i,j;
while(~scanf("%d%d%d",&m,&n,&t))
{
memset(vis,0,sizeof(vis));
for(i = 0 ; i <m ; i ++)
{
for(j = 0 ; j <n ; j ++)
{
cin>>Map[i][j];
if(Map[i][j]=='@')
{
sx = i ;sy = j ;
}
}
}
printf("%d\n",bfs());
}
}