题解 P1156 【垃圾陷阱】
先将每一个垃圾按出现时间升序排序
定义a.x为出现时间a.h为高度a.t为吃下获得的血量
f[i][j]表示前i个垃圾在到达j的高度时剩余的最大血量
显而易见开始时f[0][0]为10
枚举一个i为垃圾编号j为高度,就有:
1.吃下这个垃圾f[i][j]=max{f[i][j],f[i-1][j]-(a[i].x-a[i-1].x)+a[i].t}
初始f[i][j]为-INF,a[i].x-a[i-1].x为从上一个垃圾到这一个垃圾要经过多少时间
而且显然要当f[i-1][j]-(a[i].x-a[i-1].x)>=0时才在当前时间是存活着的才可以吃下这个垃圾,吃下这个垃圾回复的血量就是a[i].t,且这只牛很厉害可以在刚好死的时候吃下一个垃圾(+1s)
2.将这个垃圾叠起来f[i][j]=max{f[i][j],f[i-1][j-a[i].h]-a[i].x+a[i-1].x}
在这种情况中显然我们如果可以将当前垃圾放置并达到j这个高度时在当前高度减去当前垃圾的高度a[i].h,即([j-a[i].h)要有一个可以在经过(a[i].x-a[i-1].x)的时间仍然存活,当然j-a[i].h要>=0,时间为负数显然是不可能的
而且这只牛很厉害,在生命的最后一秒仍然可以堆上一个垃圾(+1s)
这时如过我们枚举的高度j达到了目标高度n(要满足血量>=0)我们就可以直接输出a[i].x
为什么呢,因为开始时我们排了一次序,且我们是以每一个垃圾为外循环进行枚举的,所以当有一个j达到了目标高度那么肯定是最优的
当我们出了最优解后就可以直接退出了
但如果没有找到最优解,那我们就重新枚举一次此时的答案ans为max{ans,f[i][j]+a[i].x}
因为在到达了的i个垃圾后我们还可以再撑f[i][j]s
这样就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x7fffffff
#define ll long long
#define one_by_one (karment[i].time-karment[i-1].time)
using namespace std;
ll sum,dep;
ll ans;
struct laji{ll time,food,high;}karment[10000];
ll dp[1005][1005];
bool cmp(laji a,laji b){return a.time<b.time;}
int main()
{
ll i,j;
//cout<<INF;
cin>>dep>>sum;
for(i=0;i<=sum;i++)
for(j=0;j<=dep;j++)dp[i][j]=-INF;
//cout<<dp[1][0];
for(i=1;i<=sum;i++)cin>>karment[i].time>>karment[i].food>>karment[i].high;
sort(karment+1,karment+sum+1,cmp);
//for(i=1;i<=sum;i++)cout<<karment[i].time<<" ";
dp[0][0]=10;
karment[0].time=0;
karment[0].high=0;
karment[0].food=0;
for(i=1;i<=sum;i++)
for(j=0;j<=dep;j++)
{
//cout<<1;
if(dp[i-1][j]-one_by_one>=0)
dp[i][j]=max(dp[i][j],dp[i-1][j]-one_by_one+karment[i].food);
if(dp[i-1][j-karment[i].high]-one_by_one>=0&&j-karment[i].high>=0)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-karment[i].high]-one_by_one);
//cout<<"nowlife: "<<dp[i][j]<<" "<<"high: "<<j<<" time: "<<karment[i].time<<endl;
if(j==dep)
{
cout<<karment[i].time;
return 0;
}
}
//cout<<"nowlife: "<<dp[i][j]<<" "<<"high: "<<j<<" time: "<<karment[i].time<<endl;
}
//cout<<1<<endl;
for(i=0;i<=sum;i++)
for(j=0;j<=dep;j++)
ans=max(ans,dp[i][j]+karment[i].time);
cout<<ans;
return 0;
}