P1156 垃圾陷阱
类似01背包,先对所有的垃圾按照时间先后排序。
dp[i][j]表示到第i个垃圾,达到高度j的最大的存活时间。
状态的转移:
1.当前垃圾用于堆:dp[i][j+h] = max(dp[i][j+h], dp[i-1][j] - 时间花费)
2.当前垃圾用于吃:dp[i][j] = max(dp[i][j], dp[i-1][j] + 吃垃圾获得的时间 - 时间花费)
时间花费表示上一个状态到当前状态要饿的时间(t[i] - t[i-1])
在状态转移的时候是有条件的,即上一个状态的生存时间是否大于到当前这个状态的时间花费
dp[i-1][j] >= t[i] - t[i-1]
判断出井:如果状态可以转移,若存在一个状态dp[i-1][j] + 当前垃圾高度h 大于等于D了,就说明可以出去了
不能出去情况下的最长时间:贪心吃掉所有的垃圾
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9+7;
struct node
{
int t,f,h;
bool operator <(const node &a)const
{
return t<a.t;
}
}p[105];
int dp[105][205];
int main()
{
int d,g;
scanf("%d%d",&d,&g);
for(int i=1;i<=g;i++)
scanf("%d%d%d",&p[i].t,&p[i].f,&p[i].h);
sort(p+1,p+1+g);
p[0].t=0;
memset(dp,-1,sizeof(dp));
dp[0][0]=10;
for(int i=1;i<=g;i++)
{
for(int j=d;j>=0;j--)
{
if(dp[i-1][j]>=p[i].t-p[i-1].t)
{
if(j+p[i].h>=d)
{
printf("%d\n",p[i].t);
return 0;
}
dp[i][j+p[i].h]=max(dp[i][j+p[i].h],dp[i-1][j]-p[i].t+p[i-1].t);
dp[i][j]=max(dp[i][j],dp[i-1][j]+p[i].f-p[i].t+p[i-1].t);
}
}
}
int ans=10;
for(int i=1;i<=g;i++)
{
if(ans<p[i].t)break;
ans+=p[i].f;
}
printf("%d\n",ans);
return 0;
}