• P1156 垃圾陷阱


    题目描述

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

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

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

    假设卡门预先知道了每个垃圾扔下的时间t(0< t<=1000),以及每个垃圾堆放的高度h(1<=h<=25)和吃进该垃圾能维持生命的时间f(1<=f<=30),要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续10小时的能量,如果卡门10小时内没有进食,卡门就将饿死。

    输入输出格式

    输入格式:

    第一行为2个整数,D 和 G (1 <= G <= 100),G为被投入井的垃圾的数量。

    第二到第G+1行每行包括3个整数:T (0 < T <= 1000),表示垃圾被投进井中的时间;F (1 <= F <= 30),表示该垃圾能维持卡门生命的时间;和 H (1 <= H <= 25),该垃圾能垫高的高度。

    输出格式:

    如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。

    输入输出样例

    输入样例#1: 复制
    20 4
    5 4 9
    9 3 2
    12 6 10
    13 1 1
    输出样例#1: 复制
    13

    说明

    [样例说明]

    卡门堆放她收到的第一个垃圾:height=9;

    卡门吃掉她收到的第二个垃圾,使她的生命从10小时延伸到13小时;

    卡门堆放第3个垃圾,height=19;

    卡门堆放第4个垃圾,height=20。

    //二维
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2600
    #define inf 0x3f3f3f3f
    struct node
    {
        int t,w,v;
    } a[maxn];
    bool cmp(node a,node b)
    {
        return a.t<b.t;
    }
    int dp[maxn][maxn];
    //dp[i][j]:代表前i个垃圾,高度为j,能得到的最大生命值
    //dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].w]-(a[i].t-a[i-1].t),dp[i-1][j]-(a[i].t-a[i-1].t)+a[i].v);
    int W,n;
    int H=0;
    int main()
    {
        cin>>W>>n;
        for(int i=1; i<=n; i++)
        {
            cin>>a[i].t>>a[i].v>>a[i].w;
            H+=a[i].w;
        }
        sort(a+1,a+1+n,cmp);//一定要时间排序
        for (int i=0; i<=n; i++)
            for (int j=0; j<=H; j++)
                dp[i][j]=-inf;
    //千万记住,不能这么写 fill(dp[0],dp[0]+(n+1)*(H+1)+1,-inf);
    //fill函数会先把每个位置都填满才跨越下一级
        dp[0][0]=10;
        for(int i=1; i<=n; i++)
            for(int j=0; j<=H; j++)
            {
                //因为条件不同的关系,需要分两次进行max更新
                if(dp[i-1][j]-a[i].t+a[i-1].t>=0)
                    dp[i][j]=max(dp[i][j],dp[i-1][j]-a[i].t+a[i-1].t+a[i].v);
                if(j-a[i].w>=0)
                    dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].w]-a[i].t+a[i-1].t);
                //提前跳出&&不死
                if(j>=W&&dp[i][j]>=0)
                {
                    cout<<a[i].t;
                    return 0;
                }
            }
        //这里血量sum一定要和a[i].t时刻这两者区分开来,他妈的
        int sum=10;
        for(int i=1; i<=n; i++)
        {
            if(sum-a[i].t+a[i-1].t<0)
            {
                cout<<a[i-1].t+sum;
                return 0;
            }
            sum=sum-a[i].t+a[i-1].t+a[i].v;
        }
        cout<<a[n].t+sum;
    
        return 0;
    }
    //一维
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2600
    #define inf 0x3f3f3f3f
    struct node{
    int t,w,v;
    }p[maxn];
    int W,n;
    int dp[maxn];
    bool cmp(node a,node b){
    return a.t<b.t;
    }
    int main()
    {
    cin>>W>>n;
    for(int i=1;i<=n;i++)
    cin>>p[i].t>>p[i].v>>p[i].w;
    sort(p+1,p+1+n,cmp);
    dp[0]=10;
    //dp[j]代表此时遍历((目标对象))为第i堆垃圾,且((冲击目标))为高度为j时,总计能存活的最长时间
    //因为我是要讨论第i,j,所以i,j是还没有遍历到的,属于目标对象
    for(int i=1;i<=n;i++)
    for(int j=W;j>=0;j--)
    if(dp[j]>=p[i].t){
    if(j+p[i].w>=W){
    cout<<p[i].t;
    return 0;
    }
    //加高
    dp[j+p[i].w]=max(dp[j+p[i].w],dp[j]);
    //加血
    dp[j]+=p[i].v;
    }
    cout<<dp[0];//这里的dp[0]的含义是反正肯定会死,所以把所有的选择全部设为吃垃圾,都不用来加高,所有高度恒为0
        return 0;
    }
  • 相关阅读:
    while练习
    运算符
    作业
    [新手必看] 17个常见的Python运行时错误
    作业
    day04
    作业
    算法模板——线段树2(区间加+区间乘+区间求和)
    1798: [Ahoi2009]Seq 维护序列seq
    1708: [Usaco2007 Oct]Money奶牛的硬币
  • 原文地址:https://www.cnblogs.com/planche/p/8438128.html
Copyright © 2020-2023  润新知