题意
给定n个工作的报酬、完成需要的天数以及截止日期,要求得出最大的报酬
例如:
3
3 3 6
2 2 3
1 3 4
有两种方案,第一种是只做工作1赚得6元,第二种是只做工作2和工作3,赚得7元,所以可得最大报酬是7元
考点
动态规划 01背包问题
不错的讲解视频推荐:【动态规划】背包问题 up主:秒懂算法
思路
动态规划的核心就是如何设计状态和状态转移方程
本题还需要判断剩余的天数是否能使当前工作完成,因此需要有一个判断
k = min(j, all[i].d)-all[i].l;
其中j
就是给予的天数,例如当一个工作需要2天完成,截止日期是3天,但是只给予了1天的时间,那么这个工作就不能被考虑,这样也无需判断其加入是否会使价值增加了
状态转移方程是一个以价值为基准判断的,而本题还有个前提:就是要在规定时间内完成所要求的工作
因此状态转移方程的设置如下:
如果k >= 0
说明该工作可以被完成,那么要进行价值判断dp[i][j] = max(dp[i-1][j],dp[i-1][k]+all[i].p;
如果k<0
说明该工作不能被完成,那么无需考虑价值判断,直接dp[i][j] = dp[i-1][j];
状态转移方程具体内容为什么是这样,可以看上面推荐的视频,讲解得特别清晰
代码
#include <iostream>
using namespace std;
#define maxn 100
#define dmax 1000
#include <algorithm>
typedef struct node
{
int p, l, d;
}node;
node all[maxn];
int n;
bool cmp(node a, node b)
{
return a.d < b.d;
}
int dp[maxn][dmax];
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> all[i].p >> all[i].l >> all[i].d;
sort(all + 1, all + n + 1, cmp);
int maxs = all[n].d;
//cout << maxs << endl;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= maxs; j++)
{
int k = min(j, all[i].d) - all[i].l;
if (k >= 0)
{
dp[i][j] = max(dp[i - 1][j], dp[i - 1][k] + all[i].p);
}
else
dp[i][j] = dp[i - 1][j];
}
/*
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= maxs; j++)
{
cout << dp[i][j] << " ";
}
cout << endl;
}
*/
cout << dp[n][maxs] << endl;
return 0;
}