卡門――農夫約翰極其珍視的一條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 */