思路
转化为背包模型,设 (dp[i][j]) 为挑选第 (i) 个物品时高度为 (j) 的累计能量值,
容易发现,状态转移的条件需要当前的时间小于等于当前的累计能量值,也就是 (dp[i][j] le t[i]),
接下来可以选择吃掉或者不吃,分类讨论:
不吃 (dp[i + 1][j + h[i]] = max (dp[i + 1][j + h[i]] ,dp[i][j]).)
吃掉 (dp[i + 1][j] = max (dp[i + 1][j] ,dp[i][j] + f[i]).)
在循环过程中如果高度等于或者超过了 (D) ,直接输出当前的时间就可以了。
循环结束后说明牛上不去,直接输出 (max (dp[i][0]|i = 1,2,cdots,G)) 即可。
代码
二维数组
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 1e2 + 10;
const int MAXT = 1e3 + 10;
struct node {
int t ,f ,h;
}a[MAXN];
bool cmp (node r1 ,node r2) {
return r1.t < r2.t;
}
int dp[MAXN][MAXT];
int D ,G;
int main () {
scanf ("%d%d",&D ,&G);
for (int q = 1;q <= G;++ q)
scanf ("%d%d%d",&a[q].t ,&a[q].f ,&a[q].h);
sort (a + 1 ,a + G + 1 ,cmp);
dp[0][0] = 10;
for (int q = 1;q <= G;++ q) {
for (int w = 0;w <= D;++ w) {
if (dp[q - 1][w] >= a[q].t) {
if (w + a[q].h >= D) {
printf ("%d
",a[q].t);
return 0;
}
dp[q][w + a[q].h] = max (dp[q][w + a[q].h] ,dp[q - 1][w]);
dp[q][w] = max (dp[q - 1][w] + a[q].f ,dp[q][w]);
}
}
}
int ans = -1;
for (int q = 1;q <= G;++ q) {
ans = max (ans ,dp[q][0]);
}
printf ("%d
",ans);
return 0;
}
一维滚动数组
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1e2 + 10;
const int MAXT = 1e3 + 10;
struct node {
int t ,f ,h;
}a[MAXN];
int dp[MAXT];//dp[i][j]表示在选第 i 个垃圾的时候,到达高度 j 时的累计生命值
int D ,G;
bool cmp (node r1 ,node r2) {
return r1.t < r2.t;
}
int main () {
scanf ("%d%d",&D ,&G);
a[0].t = a[0].h = a[0].f = 0;
for (int q = 1;q <= G;++ q) {
scanf ("%d%d%d",&a[q].t ,&a[q].f ,&a[q].h);
}
sort (a + 1 ,a + G + 1 ,cmp);
dp[0] = 10;
for (int q = 1;q <= G;++ q) {
for (int w = D;w >= 0;-- w) {
if (dp[w] >= a[q].t) {
if (w + a[q].h >= D) {
printf ("%d
",a[q].t);
return 0;
}
dp[w + a[q].h] = max (dp[w + a[q].h] ,dp[w]);
dp[w] = dp[w] + a[q].f;
}
}
}
printf ("%d
",dp[0]);
return 0;
}