思路
这是加权区间调度问题。
按结束时间排序,设 dp[i] 表示前 i 个任务能获得的最大优先级和。
转移:
-
不选第 i 个:
dp[i] = dp[i-1] -
选第 i 个:找到最后一个结束时间 ≤ 第 i 个任务开始时间的任务 j,
dp[i] = max(dp[i], dp[j] + priority[i])
因为 priority 可能为负,所以可以不选任何任务,答案为 0 或正数。
代码
c
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int start, end, priority;
} Task;
int cmp(const void *a, const void *b) {
Task *x = (Task *)a;
Task *y = (Task *)b;
return x->end - y->end;
}
int max(int a, int b) {
return a > b ? a : b;
}
int main() {
int n;
scanf("%d", &n);
Task tasks[100005];
for (int i = 0; i < n; i++)
scanf("%d %d %d", &tasks[i].start, &tasks[i].end, &tasks[i].priority);
qsort(tasks, n, sizeof(Task), cmp);
int dp[100005];
dp[0] = 0;
for (int i = 1; i <= n; i++) {
dp[i] = dp[i - 1];
int l = 0, r = i - 1, pos = 0;
while (l <= r) {
int mid = (l + r) / 2;
if (tasks[mid].end <= tasks[i - 1].start) {
pos = mid + 1;
l = mid + 1;
} else {
r = mid - 1;
}
}
dp[i] = max(dp[i], dp[pos] + tasks[i - 1].priority);
}
printf("%d\n", dp[n]);
return 0;
}