P1156 垃圾陷阱 背包dp
显然这道题可以转化成背包问题(把背包问题中的选或不选 转化为 是垫高高还是吃垃圾)
设dp[i][j]为用前i个垃圾堆成j高度的最大生命值
当吃这个食物垃圾的时候可以转移 dp[i-1][j] +rubbish[i].f -> dp[i][j](当不会死的时候才能转移)
当垫高高的时候可以转移 dp[i-1][j-rubbish[i].h] -> dp[i][j] (当不会死且j-rubbish[i].h>=0的时候才能转移)
输出答案
预先处理一下最多能活多久。 在dp数组中扫一遍,找到最小的满足要求的答案,若不存在则输出最久生存时间。
/*
* @Author: Dolphin_
* @Date: 2019-08-14 16:29:23
* @Last Modified by: Dolphin_
* @Last Modified time: 2019-08-14 16:48:30
*/
//f[i][j]表示用前i个垃圾 在j高度时能获得的最大生命值
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define FOR(i, a, b) for (int i = a; i <= b; ++i)
#define _FOR(i, a, b) for (int i = a; i >= b; --i)
#define INF 0x7fffffff
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int g,d,f[110][110];
struct node{
int t,f,h;
}a[110000];
bool cmp(node a,node b)
{
return a.t<b.t;
}
int main()
{
//freopen("a.in","r",stdin);
read(d);read(g);
int sum=10;
FOR(i,1,g)
{
read(a[i].t);read(a[i].f);read(a[i].h);
//a[i].t是垃圾掉下来的时间 a[i].f是垃圾提供的血量 a[i].h是垃圾的高度
}
sort(a+1,a+1+g,cmp);
FOR(i,1,g)
{
if(sum>=a[i].t)sum+=a[i].f;
else break;
}
f[0][0]=10;
FOR(i,1,g)
{
FOR(j,0,d)
{
//选这个吃
if(f[i-1][j]>=a[i].t) f[i][j]=max(f[i][j],f[i-1][j]+a[i].f);
//选这个垫高高
if(j>=a[i].h&&f[i-1][j-a[i].h]>=a[i].t) f[i][j]=max(f[i][j],f[i-1][j-a[i].h]) ;
}
}
int ans=INF;bool flag=true;
FOR(i,1,g)
{
if(f[i][d]!=0)
{
ans=i;
flag=false;
break;
}
}
if(flag)
{
printf("%d\n",sum);
}else
{
printf("%d\n",a[ans].t);
}
return 0;
}