2019.11.30 垃圾陷阱

題目描述

卡門――農夫約翰極其珍視的一條Holsteins奶牛――已經落了到「垃圾井」中。「垃圾井」是農夫們扔垃圾的地方,它的深度爲\(D(2 \le D \le 100)\)英尺。ios

卡門想把垃圾堆起來,等到堆得與井一樣高時,她就能逃出井外了。另外,卡門能夠經過吃一些垃圾來維持本身的生命。git

每一個垃圾均可以用來吃或堆放,而且堆放垃圾不用花費卡門的時間。數組

假設卡門預先知道了每一個垃圾扔下的時間\(t(0< t \le 1000)\),以及每一個垃圾堆放的高度\(h(1 \le h \le 25)\)和吃進該垃圾能維持生命的時間\(f(1 \le f \le 30)\),要求出卡門最先能逃出井外的時間,假設卡門當前體內有足夠持續\(10\)小時的能量,若是卡門\(10\)時內沒有進食,卡門就將餓死。spa

輸入格式

第一行爲\(2\)個整數,\(D\)\(G (1 \le G \le 100)\)\(G\)爲被投入井的垃圾的數量。code

第二到第\(G+1\)行每行包括\(3\)個整數:\(T (0 < T <= 1000)\),表示垃圾被投進井中的時間;\(F (1 \le F \le 30)\),表示該垃圾能維持卡門生命的時間;和 \(H (1 \le H \le 25)\),該垃圾能墊高的高度。排序

輸出格式

若是卡門能夠爬出陷阱,輸出一個整數表示最先何時能夠爬出;不然輸出卡門最長能夠存活多長時間。get

輸入輸出樣例

輸入 #1string

20 4
5 4 9
9 3 2
12 6 10
13 1 1

輸出 #1it

13

說明/提示

[樣例說明]io

卡門堆放她收到的第一個垃圾:\(height=9\)

卡門吃掉她收到的第\(2\)個垃圾,使她的生命從\(10\)時延伸到\(13\)時;

卡門堆放第\(3\)個垃圾,\(height=19\)

卡門堆放第\(4\)個垃圾,\(height=20\)
對於每一個垃圾,咱們有兩種處理方法:吃掉或者墊起來。
這透露出濃濃的揹包氣息。考慮\(dp\)
對於整個題來說,咱們有\(4\)個變量:當前時間/垃圾的編號/當前高度/當前生命。
這樣空間開不下,可是咱們容易觀察到對於每一個垃圾,沒有必要留着而應該直接使用,因此當前時間能夠和垃圾的編號合併。
這樣只有了\(3\)個變量。題目裏面要求求出達到高度\(d\)的最短期,因此咱們用\(dp[i][j]\)表示當降下第\(i\)道垃圾且處理完這個垃圾以後的生命爲\(j\)時,最大能夠到達的高度。原題裏面不少題解都是用\(dp[i][j]\)表示最大生命,不知道爲何。
請注意這裏的生命是從\(0\)時刻開始可以存活的總生命值。也就是說這個生命不會遞減只會增長,判斷死亡的標準是當前的生命值小於當前時間點。
對於每一個垃圾,咱們有兩種選擇:
第一,利用它提高高度。那麼\(dp[i][j]=dp[i-1][j]+h[i]\),表示第\(i\)個垃圾被用來提高了\(h[i]\)的高度。
第二,利用它回覆生命。那麼\(dp[i][j]=dp[i-1][j-f[i]]\),表示第\(i\)個垃圾被用來回復了\(f[i]\)的生命。
當咱們第一次找到了\(dp[i][j]\geq d\),則輸出\(t[i]\)以後\(return 0\),由於垃圾是按照時間順序枚舉的。
若是找不到知足要求的答案,說明沒法跳出。這時咱們的判斷策略有變化,由於要儘量活下去,也就是說應該用全部的垃圾回覆生命。因此對於每個垃圾落下的時間,咱們發現它大於當前的生命值則輸出當前生命值並結束;不然生命值加上這個垃圾的回覆量。
注意事項有三點:
第一,若是利用垃圾回覆生命,必須判斷\(j-f[i]\geq t[i]\),由於\(dp[i][j]\)的第二維表示的是處理完這個垃圾以後的生命,咱們必須判斷原來的生命能不能堅持到這個時間點。判斷的方法如上,由於生命值的定義是從\(0\)開始能堅持多長時間,與時間的增加等速同向。忘記這個點會丟失\(10-30pts\)
第二,請記得給輸入按時間排序。題目中沒有表示全部聖誡之光按照時間給出,忘記這個點會丟失\(20pts\)
第三,請記得初始化\(dp\)數組爲\(-inf\)。由於如\(dp[0][9]\)之類的狀態走不到。
上代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
#define int long long
#define rep(i,a,n) for(register int i=a;i<=n;++i)
#define dwn(i,n,a) for(register int i=n;i>=a;--i)
using namespace std;
int d,g,t[100050],f[100050],h[100050],dp[105][3050];
struct rub
{
    int t,f,h;
}a[100050];
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x==0)return;
    write(x/10);
    putchar(x%10+'0');
}
bool cmp(rub a,rub b)
{
    if(a.t==b.t)
    {
        if(a.f==b.f)return a.h<b.h;
        else return a.f<b.f;
    }
    return a.t<b.t;
}
signed main()
{
    d=read(),g=read();
    rep(i,1,g)a[i].t=read(),a[i].f=read(),a[i].h=read();
    sort(a+1,a+g+1,cmp);
    memset(dp,128,sizeof dp);
    dp[0][10]=0;
    rep(i,1,g)
    {
        rep(j,max(a[i].t,a[i].f),a[g].t+1)
        {
            dp[i][j]=dp[i-1][j]+a[i].h;
            if(j-a[i].f>=a[i].t)dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].f]);
//          printf("%lld %lld %lld\n",i,j,dp[i][j]);
            if(dp[i][j]>=d)
            {
                write(a[i].t);
                return 0;
            }
        }
    }
    int last=10;
    a[g+1].t=0x3f3f3f3f;
    rep(i,1,g+1)
    {
        if(last<a[i].t)
        {
            write(last);
            return 0;
        }
        last+=a[i].f;
    }
    return 0;
}
/*
6 5
10 30 5
40 30 5
70 30 5
100 30 5
130 2 5
*/
相關文章
相關標籤/搜索