地址:
点击打开链接
这个题目有几个很坑的地方,首先是我们需要开多一维,记录带钥匙走每一个块,和不带钥匙走是不一样的,所以我们多记录了一个。另外,不只是"."能走,“@”也能走。另外,每个状态查看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()); } }