HDU 1429

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
 
解题思路:
  承接 HDU 1253 -  胜利大逃亡 的模板(虽然我感觉改的挺多的)http://www.cnblogs.com/nicetomeetu/p/5156336.html
  依旧用 BFS 走迷宫,钥匙用 状态压缩 来解决;
  在每一步上附上 钥匙状态 ,就解决了门的问题
  将原先图的 flag[x][y] 改为 flag[x][y][key],根据 钥匙状态 的更新解决了原路返回的问题
 1 #include <iostream>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 struct pr{
 6     int x,y,t,key;//横纵轴,时间,钥匙 
 7 };
 8 const int x[10]={0,0,0,1,-1},y[10]={0,1,-1,0,0};
 9 int a,b,t,sx,sy;
10 char map[25][25];//输入图 
11 int flag[25][25][(1<<11)];
12 queue<pr> s;
13 pr q,temp;
14 
15 bool check(int x,int y){
16     return x>0&&x<=a&&y>0&&y<=b&&map[x][y]!='*';
17 }
18 
19 bool door(int x,int y,int key){
20     if(map[x][y]>='A'&&map[x][y]<='Z')
21          return (1<<(map[x][y]-'A'+1))&key;
22      return 1;
23 }
24 
25 void bfs(){
26     int i,j,k;
27     while(!s.empty()) 
28     s.pop();
29     memset(flag,0,sizeof(flag)); 
30     flag[sx][sy][0]=1;
31     q.x=sx; q.y=sy; q.t=0; q.key=0;
32     s.push(q);
33     while(!s.empty())
34     {
35         q=s.front();
36         s.pop(); 
37         if(q.t>=t){//被抓 
38             cout<<-1<<endl; return ;
39         }
40         if(map[q.x][q.y]=='^'){//找到出口 
41             cout<<q.t<<endl;
42             return;
43         }
44         for(i=1;i<=4;i++){
45             int nx=q.x+x[i];
46             int    ny=q.y+y[i];
47             int newkey=q.key;
48             if(check(nx,ny)&&door(nx,ny,newkey)){
49                 if(!flag[nx][ny][newkey]){
50                     flag[nx][ny][newkey]=1;
51                     if(map[nx][ny]>='a'&&map[nx][ny]<='z')//更新钥匙 
52                         newkey=(1<<(map[nx][ny]-'A'+1)|q.key);
53                     flag[nx][ny][newkey]=1;
54                     temp.x=q.x+x[i];
55                     temp.y=q.y+y[i];
56                       temp.t=q.t+1;
57                     temp.key=newkey;
58                     s.push(temp);
59                 }
60             }
61         }
62     }
63     cout<<-1<<endl;
64 }
65 int main()
66 {
67     int i,j;
68     for(;cin>>a>>b>>t;)
69     {
70         for(i=1;i<=a;i++)
71             for(j=1;j<=b;j++){
72                 cin>>map[i][j];
73                 if(map[i][j]=='@')
74                 {
75                     sx=i;
76                     sy=j;
77                 }
78             }
79         bfs();
80     } return 0;
81 }
我自倾杯,君且随意
原文地址:https://www.cnblogs.com/nicetomeetu/p/5156471.html