题目描述
Sam暑假找了个搬砖的活儿,每天12个小时内有1~8种转可以搬,每种的时间的工资都不一样(如搬第一种砖的时间为0时~4时,工资为5元,搬第二种砖的时间为2时~6时,工资为8元),每次搬砖必须搬完才能搬下一次转(即不可重叠,如上例中搬第一种砖就不能搬第二种转),请你帮Sam拿拿主意,怎样安排可以赚到最多的工资?
输入
输入包含八组(八种砖),每组包含三个整数:搬砖开始时间s1、结束时间s2与工资sal。(0 <= s1 < 11 , 0 < s2 <= 11 , 1 <= sal <= 10)。
输出
Sam12小时内最多可以赚到的工资。
样例输入
3 5 1
1 4 5
0 6 8
4 7 4
3 8 6
5 9 3
6 10 2
8 11 4
样例输出
13
提示
对于样例的解释:
选择工作1、工作4、工作8,可以赚到13元。
这道题三个要点。
- 使用数组dp[i]记录选择第1~第i个工作可以得到的最大工资。dp[8]是答案。
- 对所有工作排序。
- 使用数组pre[i]记录选择第[i]个工作时,之前最晚可以选择的工作。
动态转移方程:
dp[i]有两种情况:
- 选:dp[i] = 工作[i]的工资 + dp[i-1]
- 不选:dp[i] = dp[i-1]
即:dp[i] = max(bz[i].sal + dp[pre[i]], dp[i-1])
#include <bits/stdc++.h>
using namespace std;
const int N = 10;
struct BZ{
int s1,s2,sal;
}bz[N];
bool cmp(const BZ a, const BZ b){
return (a.s2 < b.s2 || (a.s2==b.s2 && a.s1 < b.s1));
}
int dp[N]; // dp[i]表示选择工作i时可以得到的最大工资
int pre[N];// pre[i]表示选择工作i时之前最早可以选择的工作
void find_pre(){
for(int i=1; i<=8; ++i)
for(int j=1; j<=8; ++j)
if(bz[i].s1 >= bz[j].s2)
pre[i] = j;
}
void dfs(){
dp[0] = bz[0].sal;
for(int i=1; i<=8; i++)
dp[i] = max(bz[i].sal + dp[pre[i]], dp[i-1]);
}
int main(){
for(int i=1; i<=8; ++i)
scanf("%d%d%d",&bz[i].s1, &bz[i].s2, &bz[i].sal);
sort(bz+1, bz+9, cmp);
find_pre();
dfs();
cout << dp[8] <<endl;
return 0;
}