勝利大逃亡(續) |
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) |
Total Submission(s): 60 Accepted Submission(s): 40 |
|
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 |
思路:BFS,用二進制表示鑰匙,那麼每個點用f[i][j][k] 表示是i.j這個點,k的二進制上的1表示擁有哪一把鑰匙測試
總複雜度2^10*20*20spa
1 /* 2 Author:wuhuajun 3 */ 4 #include <cmath> 5 #include <cstdio> 6 #include <algorithm> 7 #include <cstring> 8 #include <string> 9 #include <cstdlib> 10 #include <queue> 11 using namespace std; 12 13 typedef long long ll; 14 typedef double dd; 15 const int maxn=22; 16 const int dx[]={1,-1,0,0}; 17 const int dy[]={0,0,1,-1}; 18 char s[maxn][maxn],ch; 19 bool f[maxn][maxn][(1<<10)+10]; 20 struct qq 21 { 22 int x,y,v; 23 } ya,pu; 24 queue<qq> q; 25 int step,l,n,m,t,xx,yy,sx,sy,ex,ey,deadline,pos; 26 bool flag; 27 28 29 void close() 30 { 31 exit(0); 32 } 33 bool reach() 34 { 35 if (xx==ex && yy==ey) 36 { 37 if (step<deadline) 38 printf("%d\n",step); 39 else 40 printf("-1\n"); 41 flag=true; 42 return true; 43 } 44 return false; 45 } 46 47 void print() 48 { 49 for (int i=8;i>=1;i--) 50 printf("%d",pos & (i<<1)); 51 puts(""); 52 } 53 54 void pushin() 55 { 56 pu=ya; 57 pu.x=xx; pu.y=yy; 58 if (t!=0) 59 pu.v=ya.v | (1<<(t-1)); 60 q.push(pu); 61 } 62 63 void judge() 64 { 65 if (!(1<=xx && xx<=n && 1<=yy && yy<=m)) return; 66 ch=s[xx][yy]; 67 if (ch=='*') return;//wall 68 if (ch=='.' || ch=='@') 69 { 70 t=0; 71 if (f[xx][yy][ya.v]) return; 72 f[xx][yy][ya.v]=true; 73 pushin(); 74 return; 75 } 76 if ('a'<=ch && ch<='j') //key 77 { 78 t=ch-'a'+1; 79 pos=ya.v | (1<<(t-1)); 80 if (f[xx][yy][pos]) return;//是否到過(xx,yy)這個點 81 f[xx][yy][pos]=true; 82 pushin(); 83 } 84 else 85 { //door 86 t=ch-'A'+1; 87 if ((ya.v & (1<<(t-1)))==0) return;//在(ya.x,ya.y)點上鑰匙不能開門 88 if (f[xx][yy][ya.v]) return; 89 f[xx][yy][ya.v]=true; 90 t=0; 91 pushin(); 92 } 93 } 94 95 void work() 96 { 97 memset(f,false,sizeof(f)); 98 while (!q.empty()) q.pop(); 99 step=0; flag=true; 100 ////////////////// 101 f[sx][sy][0]=true; 102 ya.x=sx; 103 ya.y=sy; 104 ya.v=0; 105 q.push(ya); 106 while (!q.empty()) 107 { 108 step++; 109 //printf("Step:%d\n-----------------------\n",step-1); 110 l=q.size(); 111 while (l--) 112 { 113 ya=q.front(); 114 q.pop(); 115 // printf("x:%d y:%d v:%d\n",ya.x,ya.y,ya.v); 116 for (int i=0;i<4;i++) 117 { 118 xx=dx[i]+ya.x; 119 yy=dy[i]+ya.y; 120 if (reach()) return; 121 judge(); 122 } 123 } 124 } 125 printf("-1\n"); 126 } 127 128 129 void init() 130 { 131 while (scanf("%d %d %d",&n,&m,&deadline)!=EOF) 132 { 133 for (int i=1;i<=n;i++) 134 { 135 scanf("%s",s[i]); 136 for (int j=m-1;j>=0;j--) 137 s[i][j+1]=s[i][j]; 138 s[i][0]='\0'; 139 } 140 for (int i=1;i<=n;i++) 141 for (int j=1;j<=m;j++) 142 { 143 if (s[i][j]=='@') 144 { 145 sx=i;sy=j; 146 } 147 if (s[i][j]=='^') 148 { 149 ex=i; ey=j; 150 } 151 } 152 work(); 153 } 154 } 155 156 int main () 157 { 158 init(); 159 close(); 160 return 0; 161 }