9.3.3 勝利大逃亡(續)

勝利大逃亡(續)

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 }
相關文章
相關標籤/搜索