Projects
题目描述
There are n projects you can attend. For each project, you know its starting and ending days and the amount of money you would get as reward. You can only attend one project during a day.
What is the maximum amount of money you can earn?
输入
The first input line contains an integer n: the number of projects.
After this, there are n lines. Each such line has three integers ai, bi, and pi: the starting day, the ending day, and the reward.
Constraints
1 ≤ n ≤
1 ≤ ai ≤ bi ≤
1 ≤ pi ≤
输出
Print one integer: the maximum amount of money you can earn.
样例输入
4
2 4 4
3 6 6
6 8 2
5 7 3
样例输出
7
思路分析
1. 读入数据
读取项目的数量 n,创建大小为 n 的 vector 来存储每个项目的信息。node 结构体包含三个成员:a 表示项目的开始日期,b 表示项目的结束日期,p 表示项目的报酬。通过循环,依次读入每个项目的开始日期、结束日期和报酬。2. 项目排序
使用 sort 函数将 project 数组中的项目按照结束日期升序排序。3. 存储结束日期
创建一个 vector 名为 ending,用于存储排好序的项目的结束日期。通过循环将每个项目的结束日期依次存入 ending 数组中。4. 定义动态规划数组
创建一个 vector 名为 dp,dp[i] 表示考虑前 i 个项目时所能获得的最大报酬。初始化 dp[0] 为第一个项目的报酬,因为只考虑第一个项目时,最大报酬就是该项目的报酬。5. 动态规划过程
从第二个项目开始遍历,对于每个项目 i:
使用 lower_bound 函数在 ending 数组的 [0, i - 1] 区间内二分查找第一个不早于项目 i 的开始日期的项目结束日期。lower_bound 函数返回一个迭代器,指向满足条件的元素。
计算该元素在 ending 数组中的位置 pos。
如果 pos > 0,则 best 为 dp[pos - 1],表示在选择项目 i 之前所能获得的最大报酬;否则 best 为 0。
更新 dp[i] 为选择项目 i 和不选择项目 i 时的最大报酬。选择项目 i 时,最大报酬为 best + project[i].p;不选择项目 i 时,最大报酬为 dp[i - 1]。6. 输出结果
最后输出 dp[n - 1],即考虑所有项目时所能获得的最大报酬。分析给定样例:
1. 读入数据
读入项目数量 n = 4。
读入每个项目的信息:
项目 0:开始日期 a = 2,结束日期 b = 4,报酬 p = 4。
项目 1:开始日期 a = 3,结束日期 b = 6,报酬 p = 6。
项目 2:开始日期 a = 6,结束日期 b = 8,报酬 p = 2。
项目 3:开始日期 a = 5,结束日期 b = 7,报酬 p = 3。2. 项目排序
按照结束日期升序排序后,项目顺序变为:
项目 0:开始日期 a = 2,结束日期 b = 4,报酬 p = 4。
项目 1:开始日期 a = 3,结束日期 b = 6,报酬 p = 6。
项目 2:开始日期 a = 5,结束日期 b = 7,报酬 p = 3。
项目 3:开始日期 a = 6,结束日期 b = 8,报酬 p = 2。3. 存储结束日期
ending 数组为 [4, 6, 7, 8]。4. 动态规划过程
初始化:dp[0] = 4,因为只考虑第一个项目时,最大报酬就是该项目的报酬。
考虑项目 1:
项目 1 的开始日期为 3,在 ending 数组的 [0, 0] 区间内二分查找第一个不早于 3 的结束日期,找到项目 0 的结束日期 4,pos = 0。
best = 0,因为 pos = 0。
dp[1] = max(dp[0], best + project[1].p) = max(4, 0 + 6) = 6。
考虑项目 2:
项目 2 的开始日期为 5,在 ending 数组的 [0, 1] 区间内二分查找第一个不早于 5 的结束日期,找到项目 1 的结束日期 6,pos = 1。
best = dp[0] = 4。
dp[2] = max(dp[1], best + project[2].p) = max(6, 4 + 3) = 7。
考虑项目 3:
项目 3 的开始日期为 6,在 ending 数组的 [0, 2] 区间内二分查找第一个不早于 6 的结束日期,找到项目 1 的结束日期 6,pos = 1。
best = dp[0] = 4。
dp[3] = max(dp[2], best + project[3].p) = max(7, 4 + 2) = 7。5. 输出结果
最终输出 dp[3] = 7,即考虑所有项目时所能获得的最大报酬为 7。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n;
struct node{int a,b,p;
};
bool cmp(node&x,node&y){return x.b<y.b;
}
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n;vector<node>project(n);for(int i=0;i<n;i++){cin>>project[i].a>>project[i].b>>project[i].p;}sort(project.begin(),project.end(),cmp);vector<int>ending(n);for(int i=0;i<n;i++){ending[i]=project[i].b;}vector<ll>dp(n);dp[0]=project[0].p;for(int i=1;i<n;i++){auto it=lower_bound(ending.begin(),ending.begin()+i,project[i].a);int pos=it-ending.begin();ll best=(pos>0)?dp[pos-1]:0;dp[i]=max(dp[i-1],best+project[i].p);}cout<<dp[n-1];return 0;
}