P1156 垃圾陷阱 题解

题目传送门

题如其名啊,数据非常帅气

这题一眼就是dp题,而且状态的设计也比较简单

至于我考试的dp为什么不是满分

咳咳,绝对不是我状态设计得汤碗了

一看就是数据太废了,没有想到我的高级的点上

这能怪我吗???(bushi)


状态设计的有些抽象了

设dp[i][j]表示当前遍历到第i个垃圾,此时的高度为j,然后去存这个时候可以持续多长时间。

然后再看状态转移方程,有两种:

1.当上一步的持续时间大于现在的时间且当前的j可以保留垃圾时(高度之差大于等于零)dp[i][j]=max(dp[i][j],dp[i-1][j-h_i])

2.当上一步的持续时间大于现在的时间并将垃圾吃掉时dp[i][j]=max(dp[i][j],dp[i-1][j])

为什么这样写呢?

因为如果出去了,在 dp[i][n] 至 dp[i][2n] 里就会有数值,找j最小的数值

如果没有就在 dp[0][0] 至 dp[i][n-1] 找最大值

为什么是dp[0][0]?

因为你谷的数据十分毒瘤

#12#13的点,一个是吃不到一个垃圾,另一个是一个垃圾的高度直接就比井还高了

所以就可以上AC Code:

#include<bits/stdc++.h>
using namespace std;
inline int read_()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') x=x*10+(c-48),c=getchar();
    return x*f;
}
inline void out_(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x<10)
    {
        putchar(x+48);
        return ;
    }
    out_(x/10),putchar(x%10+48);
    return ;
}
int dp[105][2502];//因为是高度所以要多开一点空间
int i,j,k;
int n,m;
int maxn;
struct node{
    int t;
    int f;
    int h;
};
node a[105];
bool cmp(node xx,node yy)
{
    return xx.t<yy.t;
}
int main()
{
    n=read_(),m=read_();
    for(i=1;i<=m;++i) a[i].t=read_(),a[i].f=read_(),a[i].h=read_();
    stable_sort(a+1,a+m+1,cmp);
    dp[0][0]=10;
    for(i=1;i<=2502;++i)
    {
        dp[0][1]=-1;
    }
    maxn=10;
    for(i=1;i<=m;++i)
    {
        for(j=0;j<=max(50,2*n+2);++j)
        {
            if(j-a[i].h>=0&&a[i].t<=dp[i-1][j-a[i].h])//活着且可以堆
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]);
            }
            //不吃垃圾
            if(dp[i-1][j]>=a[i].t)//还活着
                dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i].f);
            //吃掉
        }
    }
    for(i=1;i<=m;++i)
    {
        for(j=n;j<=max(50,2*n+2);++j)
        {
            if(dp[i][j]>=a[i].t)
            {
                out_(a[i].t);
                return 0;
            }
        }
    }
    int ans;
    for(i=0;i<=m;++i)
    {
        for(j=0;j<=2*n+50;++j)
        {
            ans=max(ans,dp[i][j]);//最大存活时间
        }
    }
    out_(ans);
    return 0;
}

下班!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值