题目链接: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 }
时间: 2024-10-10 09:34:07