胜利大逃亡(续)
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12549 Accepted Submission(s): 4560
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
Author
LL
状态压缩拥有钥匙的状态,每一把钥匙对应二进制里的1与0,遇到门时取出响应位数比对即可。代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 char mp[25][25],f[21][21][1205]; 6 int n,m,sx,sy,ex,ey,head,tail,nx,ny,T,ans; 7 int dx[4]={1,-1,0,0}; 8 int dy[4]={0,0,1,-1}; 9 struct node{ 10 int x,y,k,t; 11 }q[500005]; 12 int main(){ 13 char o; 14 while(scanf("%d%d%d",&n,&m,&T) != EOF){ 15 ans = 0; 16 memset(f,0,sizeof f); 17 for(int i=1;i<=n;++i) scanf("%s",mp[i]+1); 18 for(int i=1;i<=n;++i){ 19 for(int j=1;j<=m;j++) { 20 if (mp[i][j] == '@') sx = i, sy = j; 21 if (mp[i][j] == '^') ex = i, ey = j; 22 } 23 } 24 25 head = tail = 1; 26 q[1].x = sx; q[1].y = sy; 27 f[sx][sy][0] = 1; 28 while(head <= tail){ 29 int x,y,k,t; 30 x = q[head].x;y = q[head].y;k = q[head].k;t = q[head].t; 31 //if(t == 4) printf("t=%d %d %d %d\n",t,x,y,k); 32 if(t == T-1){ 33 break; 34 } 35 for(int i=0;i<4;++i){ 36 nx = x + dx[i]; ny = y + dy[i]; 37 if(nx>0 && nx <= n && ny>0 && ny <= m){ 38 if(nx == ex && ny == ey){ 39 ans = t+1; 40 break; 41 } 42 o = mp[nx][ny]; 43 if(o == '*') continue; 44 if((o == '.' || o == '@') && !f[nx][ny][k]){ 45 q[++tail].x = nx; q[tail].y = ny; q[tail].k = k;q[tail].t = t + 1; 46 f[nx][ny][k] = 1; 47 } 48 else if(o >= 'a' && o <= 'z'){ 49 int z = k>>(o-'a') & 1; 50 if(!z){ 51 int zz = 1<<(o-'a'); 52 q[++tail].x = nx; q[tail].y = ny; q[tail].k = k + zz; q[tail].t = t + 1; 53 f[nx][ny][k+zz] = 1; 54 } 55 else if(!f[nx][ny][k]){ 56 q[++tail].x = nx; q[tail].y = ny; q[tail].k = k;q[tail].t = t + 1; 57 f[nx][ny][k] = 1; 58 } 59 } 60 else if(o >='A' && o <= 'Z'){ 61 int z = k>>(o-'A')&1; 62 if(z == 1 && !f[nx][ny][k]){ 63 q[++tail].x = nx; q[tail].y = ny; q[tail].k = k;q[tail].t = t + 1; 64 f[nx][ny][k] = 1; 65 } 66 } 67 } 68 } 69 if(ans) break; 70 head++; 71 } 72 if(ans) printf("%d\n",ans); 73 else printf("-1\n"); 74 } 75 return 0; 76 }