P1156 垃圾陷阱(背包好题)
题目描述:
卡门――农夫约翰极其珍视的一条Holsteins
奶牛――已经落了到“垃圾井”中。“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2≤D≤100)英尺。
卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。
每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。
假设卡门预先知道了每个垃圾扔下的时间t(0<t≤1000),以及每个垃圾堆放的高度h(1≤h≤25)和吃进该垃圾能维持生命的时间f(1≤f≤30),
要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续10小时的能量,如果卡门10小时内没有进食,卡门就将饿死。
思路:背包好题!一眼看过去就和背包很像,但是有限制条件,就是物品有选择的时间界限,所以我们把它排序后就能依次选择了
把物品维持的生命看作价值,高度看作容量,遍历每个物品,再从不同高度下对物品进行两种选择
dp[i]表示i高度下能维持的最大生命长度
1是用来叠高度,于是j+v[i].h这个高度下能维持的最长时间就可能更新为j这个高度下的能维持的最长时间(dp[j])
2是用来当消耗品,dp[j]+=v[i].f,当前高度能维持的生命长度+该物品能提供的天数
如果该高度下能维持的最长时间不能到达物品能被选择的最短时间,则该高度下不能对物品进行选择(松弛),即跳过它
AC代码:
#include<bits/stdc++.h> using namespace std; int d, g; struct node { int t, f, h; bool operator<(node b) { return t < b.t; } }v[105]; int dp[1005]; int main() { //freopen("test.txt", "r", stdin); scanf("%d%d", &d, &g); for (int i = 1; i <= g; i++) { scanf("%d%d%d", &v[i].t, &v[i].f, &v[i].h); } sort(v + 1, v + g + 1); //先按能选择的时间排序,然后再依次进行选择 dp[0] = 10;//初始化高度为0的时候能存活的最长时间 for (int i = 1; i <= g; i++) { //依次选择 for (int j = d; j >= 0; j--) { if (dp[j] < v[i].t)continue; //如果到达该高度能存活的最长时间小于能选择物品的时间,就不能选 //在到达该高度的情况下能存活到选择该物品 if (j + v[i].h >= d) {//如果加上该物品的高度就能满足了,输出满足时间 printf("%d\n", v[i].t); return 0; } //物品的两种用法 //1用来叠高度,松弛j+v[i].h这个高度下能存活的时间为当前高度下能存活的时间 dp[j + v[i].h] = max(dp[j + v[i].h], dp[j]); //2用来消耗,当前高度能存活的时间+物品的价值 dp[j] += v[i].f; } } printf("%d\n", dp[0]);//如果不能到达,输出高度为0能存活的最长时间 return 0; }