n,m ≤ 20 迷宮,包含:起點 @、終點 ^、牆 *、門 A-J(需對應鑰匙)、鑰匙 a-j。鑰匙拾取後永久擁有,可開對應門。求最短步數到達終點,且步數 ≤ 給定時間限制,否則輸出 -1。多測試用例。
(x, y, keys, steps),keys 為 10 位位圖(1<<10 = 1024),第 i 位表示擁有鑰匙 'a'+i。vis[x][y][keys] 三維數組。keys。其餘正常。^ 即返回步數。#include <bits/stdc++.h>
using namespace std;
const int MAXN = 25;
const int MAXK = 1<<10;
struct State { int x, y, keys, step; };
int dx[4]={-1,0,1,0}, dy[4]={0,1,0,-1};
char grid[MAXN][MAXN];
bool vis[MAXN][MAXN][MAXK];
int n, m, time_limit;
int bfs(int sx, int sy) {
memset(vis, 0, sizeof(vis));
queue q;
q.push({sx, sy, 0, 0});
vis[sx][sy][0] = true;
while (!q.empty()) {
State cur = q.front(); q.pop();
if (grid[cur.x][cur.y] == '^') return cur.step;
for (int d = 0; d < 4; ++d) {
int nx = cur.x + dx[d], ny = cur.y + dy[d];
if (nx<0||nx>=n||ny<0||ny>=m) continue;
char c = grid[nx][ny];
if (c == '*') continue;
State nxt = cur;
nxt.x = nx; nxt.y = ny; nxt.step++;
if (c >= 'A' && c <= 'J') {
int need = c - 'A';
if (!(cur.keys & (1<= 'a' && c <= 'j') {
nxt.keys = cur.keys | (1 << (c - 'a'));
}
if (!vis[nxt.x][nxt.y][nxt.keys]) {
vis[nxt.x][nxt.y][nxt.keys] = true;
q.push(nxt);
}
}
}
return -1;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
while (cin >> n >> m >> time_limit) {
int sx, sy;
for (int i = 0; i < n; ++i) {
cin >> grid[i];
for (int j = 0; j < m; ++j)
if (grid[i][j] == '@') sx = i, sy = j;
}
int ans = bfs(sx, sy);
if (ans != -1 && ans < time_limit) cout << ans << '\n';
else cout << -1 << '\n';
}
return 0;
}
狀態數 ≤ 20×20×1024 ≈ 4×10^5,BFS 邊數 ≤ 4×狀態數,時間空間均可接受。
keys & (1<。 keys | (1<。