胜利大逃亡(续)

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已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。
 

 

Input
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:

. 代表路
* 代表墙
@ 代表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 }