题目大意:
“垃圾井”的深度为D英尺。每个垃圾都可以吃或堆放,并且堆放垃圾不用花费时间。
给出每个垃圾扔下的时间t,以及每个垃圾堆放的高度h和吃进该垃圾能维持生命的时间f,卡门一开始的能量能坚持10小时,问最早什么时候可以爬出,若无法爬出则求出卡门最长可以存活多长时间。
0
题解:
转化成背包问题:
垃圾高度为物重,
可增加生命为价值,
井的高度为包的大小,
要求必须把包填满(或超出)能取得的最小价值
将垃圾按出现时间依次排序
设dp[i][j]表示前i个垃圾,到达高度j时所拥有的最长的生命时间。
dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i].v-(a[i].t-a[i-1].t))
dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]-(a[i].t-a[i-1].t))
如果有一个dp[i][j]>=0且j+a[i].h>=d,则有解,直接输出
否则找一个max{dp[i][0]+a[i].t}输出
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=1234567890;
struct Rubbish
{
int t,v,h;
bool operator < (const Rubbish &rhs)
const
{
return t<rhs.t;
}
}a[101];
int ans,n,m,dp[101][3001];
int main()
{
scanf("%d%d",&m,&n);
for (int i=1; i<=n; i++)
scanf("%d%d%d\n",&a[i].t,&a[i].v,&a[i].h);
sort(a+1,a+n+1);
for (int i=0; i<=n; i++)
for (int j=0; j<=m; j++) dp[i][j]=-INF;
dp[0][0]=10; a[0].t=0;
ans=10;
for (int i=1; i<=n; i++)
{
for (int j=m; j>=0; j--)
if (dp[i-1][j]>=a[i].t-a[i-1].t)
{
if (j+a[i].h>=m)
{
printf("%d",a[i].t);
return 0;
}
dp[i][j+a[i].h]=max(dp[i][j+a[i].h],dp[i-1][j]-(a[i].t-a[i-1].t));
dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i].v-(a[i].t-a[i-1].t));
ans=max(ans,dp[i][0]+a[i].t);
}
}
printf("%d",ans);
return 0;
}