题面
题目链接
大秦 为你打开 题目传送门
备用题面
看不了题目的看下面喵!
有一个矩形状的迷宫,它被分为 $n \times m$ 个位置。有序对(行号,列号)表示迷宫中的位置,行号从 $1$ 到 $n$ 编号,列号从 $1$ 到 $m$ 编号。
从当前位置移动到下一个位置花费一步,而且只有同时满足以下条件才能移动到下一个位置:
1、下一个位置与当前位置相邻(上下或左右,4个方向);
2、开着的门是可以通行的,但锁着的门不是;
3、不能通过一堵墙。
游戏开始时,所有的门是锁着的,一种类型的钥匙只能打开对应类型的门。只有在拿到对应钥匙之后才能打开相应的门。
经过某格子时,即可获得该格子所有钥匙。
请计算一下从 $(1,1)$ 到 $(n,m)$ 最少要花费几步。
思路
典型的走迷宫 BFS 题。但是这次他有门和钥匙,那我们状压的东西也很明显了,就是我们身上有几把钥匙,这样就可以解决门的问题了,其他基本就是最最简单的 BFS 。详见代码。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| #include<bits/stdc++.h> using namespace std;
struct node { int x, y, k, tot; };
int n, m, p; int keys[60][60]; int wall[60][60][60][60];
int dx[] = { -1, 1, 0, 0 }; int dy[] = { 0, 0, -1, 1 };
int vis[60][60][1 << 12];
void Input() { memset(wall, -1, sizeof(wall)); scanf("%d%d%d", &n, &m, &p); int k, s; int x, y, x2, y2, g; scanf("%d", &k); for (int i = 1; i <= k; i++) { scanf("%d%d%d%d%d", &x, &y, &x2, &y2, &g); wall[x][y][x2][y2] = wall[x2][y2][x][y] = g; } scanf("%d", &s); for (int i = 1; i <= s; i++) { scanf("%d%d%d", &x, &y, &g); keys[x][y] |= (1 << (g - 1)); } }
void Work() { queue<node >q; q.push((node) { 1, 1, keys[1][1], 0 }); vis[1][1][keys[1][1]] = 1; while (!q.empty()) { node f = q.front(); q.pop(); if (f.x == n && f.y == m) { printf("%d", f.tot); return; }
for (int i = 0; i < 4; i++) { int x = f.x + dx[i]; int y = f.y + dy[i];
if (x<1 || x>n || y<1 || y>m) continue; if (wall[f.x][f.y][x][y] == 0) continue; if (vis[x][y][f.k | keys[x][y]]) continue;
int dr = wall[f.x][f.y][x][y]; int ke = f.k | keys[x][y]; if (vis[x][y][ke] == 0 && (dr == -1 || (dr > 0 && (f.k & (1 << (dr - 1)))))) { vis[x][y][ke] = 1; q.push((node) { x, y, ke, f.tot + 1 }); } } } printf("-1"); }
int main() { Input(); Work(); return 0; }
|