【题解】垃圾陷阱

背包也好久,没看了……看了一道比较难的背包,再去做些简单的熟悉一遍

题目连接

解:

先来看看题目中出现的条件:时间,生命,高度。

对于每个垃圾落下来的时间,首先来一波排序。以下落时间升序排序。

怎样设计状态?

将垃圾看做物品,生命值看做价值,增加的高度看做体积。总高度即为背包容量。

那么:设dp[i][j]是第i件物品搭建到j高度时的最大生命值。

显然有,当dp[i][j]<0时,直接pass掉。

当当前高度j加上这个垃圾的高度大于等于d且当前生命值大于当前垃圾与下一个垃圾的降落时间之差时(即可以挺到垃圾下落的时间),输出那个垃圾的下落时间即可。

当当前的生命值(dp[i][j])可以挺到下一个垃圾到来时,则有:

1.不吃:dp[i+1][j+e[i].h]=dp[i][j]-(e[i].t-e[i-1].t)

2.吃:dp[i+1][j]=max(dp[i+1][j],dp[i][j]-(e[i].t-e[i-1].t)+e[i].f)

那么,继续考虑:当我们可怜的奶牛没有逃出的时候,显然,最长存活时间就是把垃圾全吃掉。那么再来一遍模拟即可。

注意:dp[i][j]有可能=0,所以刚开始要把dp数组赋值成-1.

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[2000][2000];
int d,g;
struct node{
    int t,f,h;
}e[50000];
inline bool cmp(node a,node b){return a.t<b.t;}
int main(){
    memset(dp,-1,sizeof(dp));
    scanf("%d%d",&d,&g);
    for(int i=1;i<=g;i++)scanf("%d%d%d",&e[i].t,&e[i].f,&e[i].h);
    dp[0][0]=10;
    e[0].t=e[0].f=e[0].h=0;
    sort(e+1,e+g+1,cmp);
    for(int i=0;i<g;i++){
        for(int j=0;j<=d;j++){
            if(dp[i][j]<0)continue;
            if(j+e[i+1].h>=d&&dp[i][j]>=e[i+1].t-e[i].t){
                printf("%d
",e[i+1].t);
                return 0;
            }
            if(dp[i][j]-(e[i+1].t-e[i].t)>=0){
                dp[i+1][j+e[i+1].h]=dp[i][j]-e[i+1].t+e[i].t;
                dp[i+1][j]=max(dp[i+1][j],dp[i][j]+e[i+1].f-e[i+1].t+e[i].t);
            }
        }
    }
    int m=10,sum=0;
    for(int i=1;i<=g;i++){
        if(e[i].t-e[i-1].t>m){
            printf("%d
",m+sum);
            return 0;
        }
        sum+=e[i].t-e[i-1].t;
        m-=e[i].t-e[i-1].t;
        m+=e[i].f;
    }printf("%d
",m+sum);
    return 0;
}

本人期末考试已炸,714.5年级20多……和第八差3分……酸了……

原文地址:https://www.cnblogs.com/h-lka/p/11136105.html