dp例题01. 任务价值最大化

题目Description:

  大凯有n项任务可选择去做, 分别对应有开始时间, 结束时间以及任务报酬, 同一时间内最多做一件任务, 现在大凯想知道最多能得到多少报酬, 于是把求解任务交给了你。

 

输入:第一行 为 n ——表示总共有n项任务 (n <= 5000)

   接下来n行, 每行有三个数, 分别对应第i个任务的开始时间si, 结束时间ei 以及任务报酬vi。(0 <= si < ei <1e5,  0 < vi <= 1e5)

输出:最多能获得的报酬。

 

Sample Input:

8
0 6 8
3 5 1
8 11 4
6 10 2
1 4 5
4 7 4
3 8 6
5 9 3

Sample Output

13

解题思路: dp算法

先按任务结束时间进行升序排序。

dp[i] 表示做前面 i 个 任务所能得到的最多报酬。

这里构造一个pre数组, pre[i] 表示与做第i个任务不冲突的在i之前 又与之最近的任务

dp[i]的确定:做第i个任务还是不做?  比较dp[i-1] (不做第i个)  与  dp[pre[i]] + i对应的报酬, 即: dp[i] = (dp[i-1] > dp[prev[i]] + task[i].value)? dp[i-1] : dp[prev[i]] + task[i].value;

  以下为c语言代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define maxn 5005
 4 
 5 struct e {
 6     int start, end, value;
 7 }task[maxn];
 8 
 9 // 手写快排算法
10 void quick_sort(struct e * task, int left, int right) {
11     if (left >= right) return;
12     int l = left, r = right;
13     int base = rand() % (r - l + 1) + l;
14     struct e temp = task[base];
15     task[base] = task[l];
16     task[l] = temp;
17     base = task[l].end;
18     while (l < r) {
19         while (task[r].end > base && l < r) r--;
20         if (l < r) {
21             task[l] = task[r];
22             l++;
23         }
24         while (task[l].end <= base && l < r) l++;
25         if (l < r) {
26             task[r] = task[l];
27             r--;
28         }
29     }
30     task[l] = temp;
31     quick_sort(task, left, l-1);
32     quick_sort(task, l+1, right);
33 }
34 
35 int main() {
36     int dp[maxn], prev[maxn], n;
37     scanf("%d", &n);
38     // 1到n记录, 空出0
39     for (int i = 1; i <= n; i++) {
40         scanf("%d%d%d", &task[i].start, &task[i].end, &task[i].value);
41     }
42 
43     // 根据结束时间升序排序
44     quick_sort(task, 1, n);
45 
46     // 构造prev数组     pre[i] 表示与做第i个任务不冲突的在i之前 又与之最近的任务
47     for (int i = 1; i <= n; i++) {
48         for (int j = i-1; j >= 0; j--) {
49             if (task[j].end <= task[i].start) {
50                 prev[i] = j;
51                 break;
52             }
53         }
54     }
55     
56     // 有些任务不存在pre[i], 即pre[i] = 0, 前0个任务最多价值自然为0
57     dp[0] = 0;
58 
59     for (int i = 1; i <= n; i++) {
60         dp[i] = (dp[i-1] > dp[prev[i]] + task[i].value)? dp[i-1] : dp[prev[i]] + task[i].value;
61     }
62     printf("%d\n", dp[n]);
63     return 0;
64 }

 

posted on 2020-04-04 00:26  y2ek  阅读(442)  评论(0)    收藏  举报

导航