有 n 個商品,第 i 個需要時間 tᵢ 處理,代價 cᵢ。收銀員可同時處理多個商品,但總處理時間至少覆蓋所有選中商品的時間和。求最小總代價使得 Σ(tᵢ+1) ≥ n(因為處理一個商品佔用 1 單位時間槽,實際可並行)。
將 tᵢ 視為「覆蓋能力」,每選一個商品增加 tᵢ+1 的覆蓋。目標覆蓋 ≥ n。這是經典 01 背包:
dp[j]:覆蓋能力恰為 j 的最小代價。dp[0]=0,其餘 INF。dp[j + t[i]+1] = min(dp[j + t[i]+1], dp[j] + c[i])。min{ dp[j] | j ≥ n }。#include <bits/stdc++.h>
using namespace std;
const long long INF = 4e18; // 1e18 足夠
const int N = 2005;
long long dp[N<<1], c[N], t[N];
int main() {
int n;
while (cin >> n) {
for (int i = 1; i <= n; i++) {
cin >> t[i] >> c[i];
t[i]++; // 實際覆蓋能力
}
fill(dp, dp + n + 1, INF);
dp[0] = 0;
long long ans = INF;
for (int i = 1; i <= n; i++) {
for (int j = n; j >= 0; j--) {
if (dp[j] == INF) continue;
int nj = j + t[i];
if (nj >= n) ans = min(ans, dp[j] + c[i]);
else dp[nj] = min(dp[nj], dp[j] + c[i]);
}
}
cout << ans << '\n';
}
return 0;
}
4e18 避免加法溢出(cᵢ ≤ 10⁹, n ≤ 2000)。本題是「覆蓋型 01 背包」變體,關鍵在於將「並行處理」轉化為「時間槽覆蓋」模型。逆序 DP + 狀態截斷是標準技巧,代碼極其簡潔高效。