两种状态表示方法。

①设f(i,j):处理完前i件垃圾,体力值为j的最大高度。

先按时间顺序排好序,设a[i].t为第i件垃圾出现时间,a[i].h为第i件垃圾的高度,a[i].f为第i件垃圾所提供体力值。

则f[i][j]= max{      

                                              -1                 ,状态不存在

                     f[i-1][j+a[i].t-a[i-1].t]+a[i].h      ,f[i-1][j+a[i].t-a[i-1].t] ≠ -1

                   f[i-1][j+a[i].t-a[i-1].t-a[i].f]          , j>=a[i].f并且f[i-1][j+a[i].t-a[i-1].t-a[i].f]  ≠ -1

                     }

注意有可能用完全部垃圾还没跳出去,通过最后判断ans来找到最后时间。

刚开始想用刷表法,但越想越写,越绕越晕,大概还是填表法适合背包吧。

递推时要注意,上不越界,下不越界,条件满足才能转移,小心转移到不合法或不应该转移去的位置。比如这题要不是洛谷可以看数据分析bug,漏了 j>=a[i].f这一条是非常难找到的。

#include<bits/stdc++.h>
using namespace std;

int d,g,f[155][3505],ans;
struct rubbish{
	int t,f,h;
	bool operator < (rubbish x){
		return t<x.t;
	}
}a[105];

int main()
{
	freopen("input.in","r",stdin);
//	freopen("output.out","w",stdout);
	cin>>d>>g;
	for(int i=1;i<=g;i++)cin>>a[i].t>>a[i].f>>a[i].h;
	sort(a+1,a+1+g);  
	memset(f,-1,sizeof(f));
	f[0][10]=0;
	for(int i=1;i<=g;i++)for(int j=0;j<=3000;j++)
	{
		if(f[i-1][j+a[i].t-a[i-1].t]>=0)f[i][j]=f[i-1][j+a[i].t-a[i-1].t]+a[i].h;
		if(j>=a[i].f )f[i][j]=max(f[i][j],f[i-1][j+a[i].t-a[i-1].t-a[i].f]);
	}
    //for(int i=1;i<=g+1;i++)for(int j=0;j<=30;j++)printf("f[%d][%d]=%d\n",i,j,f[i][j]);
	for(int i=1;i<=g;i++)
	{
		int flag1=0,flag2=1;//1:jump out,2:died
		for(int j=0;j<=3000;j++)
		{
			if(f[i][j]>=d){flag1=1;break;}
			if(f[i][j]>=0){flag2=0;break;}
		}
		if(flag1){ans=a[i].t;break;}
		if(flag2)
		{
			int j;
			for(j=3000;j>=0;j--)if(f[i-1][j]>=0)break;
			ans=a[i-1].t+j;
			break;
		}
	}
	if(!ans)
	{
		int j;
		for(j=3000;j>=0;j--)if(f[g][j]>=0)break;
		ans=a[g].t+j;
	}
	cout<<ans<<endl;
//	for(int i=1;i<=g;i++)cout<<a[i].t<<" "<<a[i].f<<" "<<a[i].h<<"\n";
	return 0;
}

②设f(i,j):前i件垃圾,高度为j的最大体力值。转移方程在代码里。

再次强调:

递推时要注意,上不越界,下不越界,条件满足才能转移,小心转移到不合法或不应该转移去的位置。

递推时要注意,上不越界,下不越界,条件满足才能转移,小心转移到不合法或不应该转移去的位置。

递推时要注意,上不越界,下不越界,条件满足才能转移,小心转移到不合法或不应该转移去的位置。

#include<bits/stdc++.h>
using namespace std;

int d,g,f[155][155],ans;
struct rubbish{
	int t,f,h;
	bool operator < (rubbish x){
		return t<x.t;
	}	
}a[105];

int main()
{
	freopen("input.in","r",stdin);
	cin>>d>>g;
	for(int i=1;i<=g;i++)cin>>a[i].t>>a[i].f>>a[i].h;
	sort(a+1,a+1+g);  
	memset(f,-1,sizeof(f));
	f[0][0]=10;
	for(int i=1;i<=g;i++)
	{
		bool out=0,died=1;
		for(int j=0;j<=d;j++)
		{
			if(j-a[i].h>=0 && f[i-1][j-a[i].h]-(a[i].t-a[i-1].t)>=0)f[i][j]=f[i-1][j-a[i].h]-(a[i].t-a[i-1].t);
			if(f[i-1][j]-(a[i].t-a[i-1].t)>=0)f[i][j]=max(f[i][j],f[i-1][j]-(a[i].t-a[i-1].t)+a[i].f);
			if(j==d)if(f[i][j]>=0)out=1;
			if(f[i][j]>=0)died=0;
		}
		if(out){ans=a[i].t;break;}
		else if(died)
		{
			int maxn=0;
			for(int j=0;j<=d;j++)if(f[i-1][j]>maxn)maxn=f[i-1][j];
			ans=a[i-1].t+maxn;
			break;
		}
	}
	if(!ans)
	{
		int j;
		for(j=0;j<=100;j++)if(f[g][j]>=0)break;
		ans=a[g].t+f[g][j];
	}
	cout<<ans<<endl;
	return 0;
}