[HDOJ5094] Maze (记忆化搜索,BFS,状态压缩)

题目链接:https://vjudge.net/problem/HDU-5094

题意:很典型的迷宫寻路,但是点与点之间有障碍或者门,每个点有钥匙。与其他题不同的地方是障碍不是单纯的某一个点不可以走,而是两点之间。求从一点出发到另一点最短路。

很简单,用G[][][][]存两个点之间的障碍(图大了其实也可以用unordered_map<pii,pii>)。钥匙顶多10把,用位压记录钥匙状态,bfs的时候队内节点维护当前点、钥匙拥有情况、最短路。直接记忆化搞就是了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 55;
 5 const int dx[5] = {0, 0, 1, -1};
 6 const int dy[5] = {1, -1, 0, 0};
 7 typedef struct Node {
 8     int x, y, k;
 9     Node() {}
10     Node(int x, int y, int k) : 
11       x(x), y(y), k(k) {}
12 }Node;
13 typedef pair<Node, int> pni;
14 
15 int G[maxn][maxn][maxn][maxn];
16 int key[maxn][maxn];
17 int dp[1<<10][maxn][maxn];
18 int n, m, p, k, g;
19 int x1, y1, x2, y2;
20 
21 bool ok(int x, int y) {
22     return x >= 1 && x <= n && y >= 1 && y <= m;
23 }
24 
25 int bfs() {
26     queue<pni> q;
27     memset(dp, -1, sizeof(dp));
28     q.push(pni(Node(1, 1, 0), 0));
29     dp[0][1][1] = 0;
30     while(!q.empty()) {
31         pni tmp = q.front(); q.pop();
32         x1 = tmp.first.x, y1 = tmp.first.y; k = tmp.first.k;
33         if(x1 == n && y1 == m) return tmp.second;
34         for(int i = 0; i < 4; i++) {
35             x2 = x1 + dx[i];
36             y2 = y1 + dy[i];
37             if(!ok(x2, y2) || !G[x1][y1][x2][y2]) continue;
38             if(G[x1][y1][x2][y2] != -1) {
39                 if(!((1 << (G[x1][y1][x2][y2]) - 1) & k)) continue;
40             }
41             int st = k | key[x2][y2];
42             if(dp[st][x2][y2] == -1) {
43                 dp[st][x2][y2] = tmp.second + 1;
44                 q.push(pni(Node(x2, y2, st), tmp.second+1));
45             }
46         }
47     }
48     return -1;
49 }
50 
51 int main() {
52     // freopen("in", "r", stdin);
53     while(~scanf("%d%d%d",&n,&m,&p)) {
54         scanf("%d", &k);
55         memset(G, -1, sizeof(G));
56         memset(key, 0, sizeof(key));
57         for(int i = 0; i < k; i++) {
58             scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
59             G[x1][y1][x2][y2] = G[x2][y2][x1][y1] = g;
60         }
61         scanf("%d", &k);
62         for(int i = 0; i < k; i++) {
63             scanf("%d%d%d",&x1,&y1,&g);
64             key[x1][y1] |= (1 << (g - 1));
65         }
66         cout << bfs() << endl;
67     }
68     return 0;
69 }
原文地址:https://www.cnblogs.com/kirai/p/6785318.html