hdu1429 胜利大逃亡(续)???天天逃亡???

题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1429/

题目就是迷宫问题的变种,给出一张地图,上面分布着钥匙和门,一种要是只能开一种特定的门,给出起点和终点,问在t时间内是否能够走到终点。这个问题显然是要用bfs解决,但是状态量除了位置之外还有钥匙,持有的钥匙不同到达同一个位置也是状态空间中的一种不同的状态,所以用三维记录状态,状态的记录可以用二进制进行状态压缩,毕竟钥匙只有有和无两种状态。

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define dbg(args) cout<<#args<<":"<<args<<endl;
17 #define inf 0x3f3f3f3f
18 #define maxn 25
19 int n,m,t;
20 char Map[maxn][maxn];
21 int sx,sy,tx,ty;
22 bool vis[maxn][maxn][(1<<10)];//钥匙最多是2^10-1种状态 
23 int dir[][2]={0,1,0,-1,1,0,-1,0};
24 struct node{
25     int x,y,step;
26     int key;//钥匙也是一种状态,所以考虑状态压缩存储有限的钥匙的状态 
27     node(int x,int y,int s,int key):x(x),y(y),step(s),key(key){}
28     node(){}
29 };
30 node cur,nxt;
31 int bfs()
32 {
33     queue<node>q;//选择队列这种结构在于队列前面的结点step值小,step是连续变化的值
34     q.push(node(sx,sy,0,0));
35     vis[sx][sy][0]=1; 
36     while(!q.empty())
37     {
38         cur=q.front();
39         q.pop();
40         if(cur.x==tx&&cur.y==ty&&cur.step<t)
41         {
42             return cur.step;
43         }
44         f(i,0,3)
45         {
46             nxt=cur;
47             nxt.x+=dir[i][0];
48             nxt.y+=dir[i][1];
49             nxt.step++;
50             if(nxt.x<1||nxt.x>n||nxt.y<1||nxt.y>m||Map[nxt.x][nxt.y]=='*')continue;
51             if(vis[nxt.x][nxt.y][nxt.key])continue;//相对于非门非钥匙的位置,首先判断是否已经入队 
52             char c=Map[nxt.x][nxt.y];
53             if(c>='a'&&c<='j')
54             {
55                 nxt.key|=(1<<(c-'a'));//用二进制将状态压缩进每一位中 
56                 if(vis[nxt.x][nxt.y][nxt.key])continue;
57             }
58             if(c>='A'&&c<='J')
59             {
60                 if(!(nxt.key&(1<<(c-'a'))))continue;//遇到门的时候钥匙的状态不会改变,所以不必重复检查状态是否发生变化 
61             }
62             vis[nxt.x][nxt.y][nxt.key]=1;//上面筛选掉所有不能入队的状态,剩余的状态都必须进队 
63                 q.push(nxt);
64         }
65     }
66     return -1;
67 }
68 int main()
69 {
70     //freopen("input.txt","r",stdin);
71     //freopen("output.txt","w",stdout);
72     std::ios::sync_with_stdio(false);
73     while(scanf("%d%d%d",&n,&m,&t)!=EOF)
74     {
75         mem(vis,false); 
76         f(i,1,n)
77             f(j,1,m)
78             {
79                 scanf(" %c",&Map[i][j]);
80                 if(Map[i][j]=='@')sx=i,sy=j;
81                 if(Map[i][j]=='^')tx=i,ty=j;
82             }
83             pf("%d
",bfs());
84     }
85  } 
原文地址:https://www.cnblogs.com/randy-lo/p/12511804.html