题解
~~~~~ 这道题的关键在于:你不能在死了之后通过吃东西复活,所以我们在状态转移的时候只转移活着的状态。
~~~~~ 先考虑第一问:最早什么时候可以爬出。将物品按时间排序,用 f i f_i fi 表示吃了第 i i i 个物品能续命多久, h i h_i hi 表示能搭多高。设 d p i dp_{i} dpi 表示生命值为 i i i 的情况下的最大高度,对于每个物品有两种选择——吃或搭。如果选搭, d p [ i ] = m a x ( d p [ i ] , d p [ i ] + h ) dp[i]=max(dp[i],dp[i]+h) dp[i]=max(dp[i],dp[i]+h) 即 d p [ i ] = d p [ i ] + h dp[i]=dp[i]+h dp[i]=dp[i]+h,如果选择吃 d p [ i + f ] = m a x ( d p [ i + f ] , d p [ i ] ) dp[i+f]=max(dp[i+f],dp[i]) dp[i+f]=max(dp[i+f],dp[i])。
~~~~~ 再来看第二问:最长可以存活多长时间。那就是要全选择吃,贪心即可。
代码
#include<bits/stdc++.h>
#define ll long long
#define fir first
#define sec second
using namespace std;
ll d,g,dp[3005],mx=10;
// 时间,f,h
pair<ll,pair<ll,ll>>c[105];
signed main(){
ios::sync_with_stdio(false);
cin>>d>>g;
for(ll i=1;i<=g;i++)
cin>>c[i].fir>>c[i].sec.fir>>c[i].sec.sec;
sort(c+1,c+1+g);
memset(dp,-0x3f,sizeof(dp));
for(ll i=1;i<=10;i++)dp[i]=0;
for(ll i=1;i<=g;i++){
ll t=c[i].fir,x=c[i].sec.fir,y=c[i].sec.sec;
if(mx>=t)mx+=x;
for(ll j=3000-x;j>=t;j--){
dp[j+x]=max(dp[j+x],dp[j]);
dp[j]+=y;
}
for(ll j=1;j<=3000;j++){
if(dp[j]>=d){
cout<<t;
return 0;
}
}
}
cout<<mx<<endl;
return 0;
}
~~~~~ 引用请附名 —— —— —— OMG_NOIP