也是一眼能看出来的01背包,但是状态不太好选择,可以选择时间也可以选择高度,其实都差不多,时空要求比较低,我选择高度作为的状态,选择了状态和决策之后,状态转移方程就显而易见了,比较难处理的是对于不能达到时的情况,第一遍提交的时候有一个点没过,就是因为第二种情况没写好,不过其实画个图还蛮好写的。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
int sumt,uppon,dp[1010][110],n,d,m;
struct trash{
int t,f,h;
}tr[110];
int cmp(const trash &a,const trash &b){return a.t<b.t;}
int main()
{
//freopen("std.in","r",stdin);
sumt=10;uppon=0;
cin>>d>>n;
for (int i=1;i<=n;i++)
cin>>tr[i].t>>tr[i].f>>tr[i].h;
sort(tr+1,tr+n+1,cmp);
memset(dp,-1,sizeof(dp));
dp[0][0]=10;tr[0].t=0;tr[0].f=0;
for (int i=1;i<=n;i++)
{
int c=tr[i].t-tr[i-1].t;
uppon+=tr[i].h;
for (int j=uppon;j>=0;j--)
{
if (dp[i-1][j]>=c)//注意这里的边界值,题目没有说明,但是样例里已经暗示了
dp[i][j]=max(dp[i][j],dp[i-1][j]+tr[i].f-c);
if (j>=tr[i].h)dp[i][j]=max(dp[i][j],dp[i-1][j-tr[i].h]-c);
if (j>=d&&dp[i][j]>=0){cout<<tr[i].t;return 0;}
}
}
int ans=10,k;
for (int i=1;i<=n;i++)//判断如果到达不了的话
{
ans+=tr[i].f;k=sumt;
sumt=sumt+tr[i-1].t-tr[i].t+tr[i-1].f;
if (sumt<0){cout<<ans-tr[i].f;return 0;}
}
cout<<ans;
return 0;
}