HDU-1429 胜利大逃亡(续) (BFS+状态压缩)
Problem Description
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。
Input
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:
. 代表路
* 代表墙
@ 代表Ignatius的起始位置
^ 代表地牢的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。
. 代表路
* 代表墙
@ 代表Ignatius的起始位置
^ 代表地牢的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。
Output
针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。
Sample Input
4 5 17
@A.B.
a*.*.
*..*^
c..b*
4 5 16
@A.B.
a*.*.
*..*^
c..b*
Sample Output
16
-1
题目大意:在迷宫中,有一些门锁着,每个门对应一把钥匙,只有拥有门的钥匙才能经过该门。要求在规定的时间内走出迷宫。注意:门不是迷宫的出口。
题目分析:主要问题就是状态表示。总共钥匙数不超过10把,容易想到状态压缩。当遇到一把新钥匙时,通过“|”运算来改变状态,当遇到门时,用“&”运算来判断是否已经拥有该门的钥匙。
代码如下:
1 # include<iostream> 2 # include<cstdio> 3 # include<queue> 4 # include<cstring> 5 # include<algorithm> 6 using namespace std; 7 int vis[25][25][1050]; 8 char p[25][25]; 9 int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 10 struct node 11 { 12 int x,y,t,s; 13 node(int a,int b,int c,int d):x(a),y(b),t(c),s(d){} 14 }; 15 void bfs(int sx,int sy,int n,int m,int T) 16 { 17 memset(vis,0,sizeof(vis)); 18 queue<node>q; 19 vis[sx][sy][0]=1; 20 q.push(node(sx,sy,0,0)); 21 int cnt=0; 22 while(!q.empty()) 23 { 24 node u=q.front(); 25 q.pop(); 26 if(u.t>=T) 27 continue; 28 int x=u.x,y=u.y; 29 if(p[x][y]=='^'){ 30 printf("%d\n",u.t); 31 return ; 32 } 33 for(int i=0;i<4;++i){ 34 int nx=x+d[i][0],ny=y+d[i][1]; 35 if(nx<0||nx>=n||ny<0||ny>=m) 36 continue; 37 if(p[nx][ny]=='*') 38 continue; 39 int s=u.s; 40 if(p[nx][ny]>='A'&&p[nx][ny]<='J'&&!(s&(1<<p[nx][ny]-'A'))) 41 continue; 42 if(p[nx][ny]>='a'&&p[nx][ny]<='j') 43 s=s|(1<<(p[nx][ny]-'a')); 44 if(vis[nx][ny][s]) 45 continue; 46 vis[nx][ny][s]=1; 47 q.push(node(nx,ny,u.t+1,s)); 48 } 49 } 50 printf("-1\n"); 51 } 52 int main() 53 { 54 int n,m,t,sx,sy; 55 while(scanf("%d%d%d",&n,&m,&t)!=EOF) 56 { 57 int cnt=0; 58 for(int i=0;i<n;++i){ 59 scanf("%s",p[i]); 60 for(int j=0;j<m;++j){ 61 if(p[i][j]=='@') 62 sx=i,sy=j; 63 } 64 } 65 bfs(sx,sy,n,m,t); 66 } 67 return 0; 68 }