n×m 迷宮(n,m≤20),@ 起點,^ 終點,* 牆,a-j 鑰匙,A-J 對應門。限時 t 步內到達終點。求最短步數,不可達輸出 -1。
(x,y)mask,10 位對應 a~j,1 表示持有vis[x][y][mask],三維數組去重狀態數上限:20×20×2¹⁰ = 400×1024 ≈ 41萬,BFS 完全可行。
struct Node { int x, y, mask, step; };
int bfs() {
queue<Node> q;
q.push({sx, sy, 0, 0});
vis[sx][sy][0] = true;
while (!q.empty()) {
Node cur = q.front(); q.pop();
if (cur.step >= T) continue;
if (cur.x == ex && cur.y == ey) 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 cell = mp[nx][ny];
if (cell == '*') continue; // 牆
if (vis[nx][ny][cur.mask]) continue; // 已訪問
int nmask = cur.mask;
if (cell >= 'A' && cell <= 'J') { // 門
int need = cell - 'A';
if (!(cur.mask & (1<= 'a' && cell <= 'j') { // 撿鑰匙
nmask |= 1 << (cell - 'a');
}
vis[nx][ny][nmask] = true;
q.push({nx, ny, nmask, cur.step+1});
}
}
return -1;
}
vis[x][y][mask] 區分不同鑰匙狀態下到達同一位置,避免錯誤剪枝。2¹⁰ 次。cur.step >= T 直接丟棄。#include <bits/stdc++.h>
using namespace std;
const int MAXN = 25;
const int MAXM = 1<<10;
int n, m, T;
char mp[MAXN][MAXN];
bool vis[MAXN][MAXN][MAXM];
int dx[4]={1,0,-1,0}, dy[4]={0,1,0,-1};
int sx, sy, ex, ey;
struct Node { int x, y, mask, step; };
int bfs() {
memset(vis, 0, sizeof(vis));
queue<Node> q;
q.push({sx, sy, 0, 0});
vis[sx][sy][0] = true;
while (!q.empty()) {
Node cur = q.front(); q.pop();
if (cur.step >= T) continue;
if (cur.x == ex && cur.y == ey) 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 = mp[nx][ny];
if (c == '*') continue;
if (vis[nx][ny][cur.mask]) continue;
int nmask = cur.mask;
if (c >= 'A' && c <= 'J') {
int need = c - 'A';
if (!(cur.mask & (1<= 'a' && c <= 'j') {
nmask |= 1 << (c - 'a');
}
vis[nx][ny][nmask] = true;
q.push({nx, ny, nmask, cur.step+1});
}
}
return -1;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
while (cin >> n >> m >> T) {
for (int i=0;i> mp[i];
for (int j=0;j
複雜度分析
- 狀態數:
O(n·m·2^k),k=10 固定
- 每狀態轉移
O(4)
- 總時間
O(n·m·2^k) ≈ 400×1024×4 ≈ 1.6e6,極快
- 空間
vis[20][20][1024] ≈ 400KB
拓展:網絡賽同類題更難點
- 多把鑰匙開同一門、門可重複通過、鑰匙可丟棄
- 需更複雜的狀態機或 A* 啟發式搜索