P1156 垃圾陷阱 TJ
思路
转化为背包模型,设 \(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\n",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\n",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\n",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\n",dp[0]);
return 0;
}
cb