N 種物品,每種有體積 v、價值 w、數量 m(m=1 為 01 背包,m=-1 為完全背包,m>1 為多重背包)。背包容量 V。求最大價值。N ≤ 200, V ≤ 200,000。
若物品 i 被物品 j 完全支配(v_i ≥ v_j 且 w_i ≤ w_j),則 i 永遠不會被選,可刪除。規則:
去重後物品數大幅減少,避免 TLE。
void zero_pack(int cost, int weight) { // 01 背包
for (int j = V; j >= cost; --j) f[j] = max(f[j], f[j-cost] + weight);
}
void complete_pack(int cost, int weight) { // 完全背包
for (int j = cost; j <= V; ++j) f[j] = max(f[j], f[j-cost] + weight);
}
void multi_pack(int cost, int weight, int amount) { // 多重背包(二進制拆分)
if (cost * amount >= V) { complete_pack(cost, weight); return; }
int k = 1;
while (k < amount) {
zero_pack(cost * k, weight * k);
amount -= k; k <<= 1;
}
zero_pack(cost * amount, weight * amount);
}
int main() {
int n = read(), V = read();
// 讀入 v[i], w[i], m[i]
// 去重標記 vis[i]
for (int i = 1; i <= n; ++i)
for (int j = i+1; j <= n; ++j)
// 根據 m[i], m[j] 判斷支配關係,標記 vis
for (int i = 1; i <= n; ++i) {
if (m[i] == 1 && !vis[i]) zero_pack(v[i], w[i]);
else if (m[i] == -1) complete_pack(v[i], w[i]);
else if (!vis[i]) multi_pack(v[i], w[i], m[i]);
}
write(f[V]);
return 0;
}
使用自訂 read()、write() 替代 cin/cout,大幅提升輸入輸出速度,對大數據量至關重要。