本題核心是將「購買指定數量商品,可使用優惠套餐」轉化為多維度完全背包問題。關鍵在於用 6 進制狀態壓縮表示購買狀態。
最多 5 種商品,每種最多買 5 件 → 每維基數為 6。狀態 S = c₀ + c₁×6 + c₂×6² + c₃×6³ + c₄×6⁴,其中 cᵢ 為第 i 種商品購買數量。目標狀態由需求數量決定。
將每種單品與優惠套餐統一視為「物品」:
完全背包轉移:dp[newState] = min(dp[newState], dp[oldState] + price)
const int MAXS = 6*6*6*6*6; // 7776 狀態
int dp[MAXS], sixPow[6] = {1,6,36,216,1296,7776};
void CompletePack() {
fill(dp, dp+MAXS, INF);
dp[0] = 0;
for (int s = 0; s < targetState; ++s) {
if (dp[s] == INF) continue;
for (int j = 0; j < totalItems; ++j) {
int ns = s + items[j].state;
if (ns > targetState) continue;
dp[ns] = min(dp[ns], dp[s] + items[j].price);
}
}
cout << dp[targetState] << endl;
}
狀態數 7776,物品數 ≤ 104,時間 O(狀態數 × 物品數) ≈ 8×10⁵,極快。