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
",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;
}