N ≤ 10 個城市,m ≤ 10 條有向道路。每條路 (a, b, c, p, r) 表示:從 a 到 b,若「之前到過或當前在城市 c」則費用 p,否則 r(p ≤ r)。求從 1 到 N 的最小費用,不可達輸出 impossible。
(當前城市, 已訪問城市集合, 當前費用)。集合用 10 位 bitmask 表示。void dfs(int u, int mask, int cost) {
if (vis[u] > 5) return; // 剪枝:單城訪問上限
mask |= 1 << (u - 1); // 標記已訪問
if (u == N) { ans = min(ans, cost); return; }
for (each road i from u) {
int v = road[i].b;
++vis[v];
if (mask & (1 << (road[i].c - 1))) // 已訪問過城市 c
dfs(v, mask, cost + road[i].p);
else
dfs(v, mask, cost + road[i].r);
--vis[v]; // 回溯
}
}
mask 只記錄「是否到過」,不記錄次數,符合題意「之前經過或現在位於」。ans = INF, vis[] = 0。ans 保持 INF 時輸出 impossible。狀態數上界 N × 2ᴺ × 5ᴺ 理論極大,但實際圖極稀疏(m ≤ 10),搜尋樹極窄,瞬間通過。
本題展示了「小規模圖 + 狀態依賴歷史」時,DFS + bitmask + 經驗剪枝 往往比 Dijkstra/SPFA 更簡潔有效。關鍵在於識別「已訪問集合」僅需布爾屬性,並設定合理的單點訪問上限避免無限遞迴。