Luogu P1156 垃圾陷阱___dp

题目大意:

“垃圾井”的深度为D英尺。每个垃圾都可以吃或堆放,并且堆放垃圾不用花费时间。
给出每个垃圾扔下的时间t,以及每个垃圾堆放的高度h和吃进该垃圾能维持生命的时间f,卡门一开始的能量能坚持10小时,问最早什么时候可以爬出,若无法爬出则求出卡门最长可以存活多长时间。

0

题解:

转化成背包问题:
垃圾高度为物重,
可增加生命为价值,
井的高度为包的大小,
要求必须把包填满(或超出)能取得的最小价值
将垃圾按出现时间依次排序
设dp[i][j]表示前i个垃圾,到达高度j时所拥有的最长的生命时间。
dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i].v-(a[i].t-a[i-1].t))
dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]-(a[i].t-a[i-1].t))
如果有一个dp[i][j]>=0且j+a[i].h>=d,则有解,直接输出
否则找一个max{dp[i][0]+a[i].t}输出

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

const int INF=1234567890;

struct Rubbish
{
    int t,v,h;
    bool operator < (const Rubbish &rhs) 
    const 
    {
        return t<rhs.t;
    }
}a[101];

int ans,n,m,dp[101][3001];

int main()
{
    scanf("%d%d",&m,&n);
    for (int i=1; i<=n; i++)
        scanf("%d%d%d\n",&a[i].t,&a[i].v,&a[i].h);
    sort(a+1,a+n+1);
    for (int i=0; i<=n; i++)
         for (int j=0; j<=m; j++) dp[i][j]=-INF;
    dp[0][0]=10; a[0].t=0;
    ans=10;
    for (int i=1; i<=n; i++)
        {
            for (int j=m; j>=0; j--)
                if (dp[i-1][j]>=a[i].t-a[i-1].t) 
                {
                    if (j+a[i].h>=m)
                       {
                           printf("%d",a[i].t);
                           return 0;
                       }            
                     dp[i][j+a[i].h]=max(dp[i][j+a[i].h],dp[i-1][j]-(a[i].t-a[i-1].t));
                     dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i].v-(a[i].t-a[i-1].t)); 
                     ans=max(ans,dp[i][0]+a[i].t);      
                }
        }           
    printf("%d",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值