M 天假期,N 份工作。每份工作有起始日 s、結束日 e、工資 c。工作不可重疊(時間不衝突)。求最大總工資。
經典加權區間調度問題。按結束時間排序,DP[i] = 前 i 天最大工資。
對每個工作 (s,e,c),對天數 j 從 M 遞減到 e:
dp[j] = max(dp[j], dp[s-1] + c);
含義:在第 j 天結束時,選擇做這個工作(從 s 到 e),獲得工資 c,加上 s-1 天前的最優值。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Job { int s, e, c; } jobs[10005];
bool cmp(const Job& a, const Job& b) { return a.e < b.e; }
int dp[10005];
int main() {
int T; scanf("%d", &T);
while (T--) {
int m, n; scanf("%d%d", &m, &n);
for (int i = 0; i < n; i++) scanf("%d%d%d", &jobs[i].s, &jobs[i].e, &jobs[i].c);
sort(jobs, jobs+n, cmp);
memset(dp, 0, sizeof(dp));
for (int i = 0; i < n; i++) {
for (int j = m; j >= jobs[i].e; j--) {
dp[j] = max(dp[j], dp[jobs[i].s - 1] + jobs[i].c);
}
}
printf("%d\n", dp[m]);
}
return 0;
}
輸入:
1 10 5 1 5 100 3 10 10 5 10 100 1 4 2 6 12 266
工作按 e 排序:(1,4,2), (1,5,100), (3,10,10), (5,10,100), (6,12,266)
最優選擇:(1,4,2) + (5,10,100) = 102,匹配樣例輸出。