【luogu P1156 垃圾陷阱】 题解

本文详细解析了洛谷P1156题目中的垃圾回收算法,通过动态规划解决最大生存时间问题。阐述了状态转移方程,如何在限制条件下最大化生存时间与高度,并附带完整代码实现。

题目链接:https://www.luogu.org/problemnew/show/P1156

\(dp[i][j]\)表示前i堆到达高度j时的所活最长时间
那么一旦到当前状态能到达满足的时间和高度就输出这个垃圾来的时间
转移时先满足可以到达的时间,
再有转移高度:\(dp[i+1][j+a[i+1].h] = dp[i][j] - (a[i+1].t - a[i].t)\)
转移生命值:\(dp[i+1][j] = max(dp[i][j]+a[i+1].f-(a[i+1].t-a[i].t), dp[i+1][j])\)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
int dp[1010][1010], n, m, d;
struct trash{
    int t, h, f;
}a[maxn];
bool cmp(trash a, trash b)
{ 
    if(a.t == b.t) return a.h > b.h;
    return a.t < b.t;
}
int main()
{
    //freopen("testdata.in","r",stdin);
    ios::sync_with_stdio(false);
    //dp[i][j]表示 前i堆能到j高度所活的最长时间 
    cin>>d>>n;
    for(int i = 1; i <= n; i++) cin>>a[i].t>>a[i].f>>a[i].h;
    sort(a+1, a+1+n, cmp);
    memset(dp, -1, sizeof(dp));
    dp[0][0] = 10;
    a[0].t = 0, a[0].f = 0, a[0].h = 0;
    for(int i = 0; i < n; i++)
        for(int j = 0; j <= d; j++)
        {
            if(dp[i][j] < 0) continue;
            if(dp[i][j] >= a[i+1].t-a[i].t && j + a[i+1].h >= d) {cout<<a[i+1].t; return 0;}
            if(dp[i][j] >= a[i+1].t-a[i].t) dp[i+1][j+a[i+1].h] = dp[i][j]-a[i+1].t+a[i].t;
            if(dp[i][j] >= a[i+1].t-a[i].t) dp[i+1][j] = max(dp[i][j]+a[i+1].f-(a[i+1].t-a[i].t), dp[i+1][j]);
        }
    int now = 10;
    for(int i = 1; i <= n; i++)
    {
        if(a[i].t - a[i-1].t > now) {printf("%d",now+a[i-1].t); return 0;}
        if(a[i].t - a[i-1].t <= now) {now += a[i].f; now = now - (a[i].t - a[i-1].t);}
    }
    cout<<a[n].t+now;
    return 0;
}

转载于:https://www.cnblogs.com/MisakaAzusa/p/9808685.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值