HDU 1248《寒冰王座》將完全背包問題包裝在死亡騎士購買藥水的情境中:手持面值 N 元鈔票(N ≤ 10,000),商店販售三種道具——血瓶 150 元、魔法藥 200 元、無敵藥水 350 元,不找零,多餘金額視為小費。目標是找出最小小費,即最大化花費金額不超過 N。
這是標準的完全背包:物品無限供給,體積即價格,價值同體積,求容量 N 下的最大價值,答案為 N - dp[N]。
dp[j]:花費不超過 j 元時的最大實際花費金額dp[0..N] = 0cost,對 j = cost .. N 執行 dp[j] = max(dp[j], dp[j-cost] + cost)int dp[10005];
int cost[3] = {150, 200, 350};
for (int i = 0; i < 3; ++i) {
for (int j = cost[i]; j <= N; ++j) {
dp[j] = max(dp[j], dp[j - cost[i]] + cost[i]);
}
}
printf("%d\n", N - dp[N]);
memset(dp, 0, sizeof(dp)) 重置。N - dp[N] 即為最小小費,樣例 N=900 可湊齊 900(150×6 或 200×3+150×2 等),小費 0;N=250 最大花費 200,小費 50。#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[10005];
int cost[3] = {150, 200, 350};
int main() {
int T, N;
scanf("%d", &T);
while (T--) {
memset(dp, 0, sizeof(dp));
scanf("%d", &N);
for (int i = 0; i < 3; ++i) {
for (int j = cost[i]; j <= N; ++j) {
dp[j] = max(dp[j], dp[j - cost[i]] + cost[i]);
}
}
printf("%d\n", N - dp[N]);
}
return 0;
}
若物品數量變多(如 M 種),相同邏輯適用。若需輸出具體購買方案,可額外維護 pre[j] 記錄最後加入的物品索引,反向追蹤即可。本題因物品極少、價值等於體積,是完全背包最精簡的教學案例。