P1156 垃圾陷阱(背包好题)

题目描述:

卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中。“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2D100)英尺。

卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。

每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。

假设卡门预先知道了每个垃圾扔下的时间t(0<t1000),以及每个垃圾堆放的高度h(1h25)和吃进该垃圾能维持生命的时间f(1f30),

要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续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;
}

 

 
posted @ 2021-03-21 21:36  cono奇犽哒  阅读(46)  评论(0)    收藏  举报