背包也好久,没看了……看了一道比较难的背包,再去做些简单的熟悉一遍
解:
先来看看题目中出现的条件:时间,生命,高度。
对于每个垃圾落下来的时间,首先来一波排序。以下落时间升序排序。
怎样设计状态?
将垃圾看做物品,生命值看做价值,增加的高度看做体积。总高度即为背包容量。
那么:设dp[i][j]是第i件物品搭建到j高度时的最大生命值。
显然有,当dp[i][j]<0时,直接pass掉。
当当前高度j加上这个垃圾的高度大于等于d且当前生命值大于当前垃圾与下一个垃圾的降落时间之差时(即可以挺到垃圾下落的时间),输出那个垃圾的下落时间即可。
当当前的生命值(dp[i][j])可以挺到下一个垃圾到来时,则有:
1.不吃:dp[i+1][j+e[i].h]=dp[i][j]-(e[i].t-e[i-1].t)
2.吃:dp[i+1][j]=max(dp[i+1][j],dp[i][j]-(e[i].t-e[i-1].t)+e[i].f)
那么,继续考虑:当我们可怜的奶牛没有逃出的时候,显然,最长存活时间就是把垃圾全吃掉。那么再来一遍模拟即可。
注意:dp[i][j]有可能=0,所以刚开始要把dp数组赋值成-1.
代码:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; int dp[2000][2000]; int d,g; struct node{ int t,f,h; }e[50000]; inline bool cmp(node a,node b){return a.t<b.t;} int main(){ memset(dp,-1,sizeof(dp)); scanf("%d%d",&d,&g); for(int i=1;i<=g;i++)scanf("%d%d%d",&e[i].t,&e[i].f,&e[i].h); dp[0][0]=10; e[0].t=e[0].f=e[0].h=0; sort(e+1,e+g+1,cmp); for(int i=0;i<g;i++){ for(int j=0;j<=d;j++){ if(dp[i][j]<0)continue; if(j+e[i+1].h>=d&&dp[i][j]>=e[i+1].t-e[i].t){ printf("%d ",e[i+1].t); return 0; } if(dp[i][j]-(e[i+1].t-e[i].t)>=0){ dp[i+1][j+e[i+1].h]=dp[i][j]-e[i+1].t+e[i].t; dp[i+1][j]=max(dp[i+1][j],dp[i][j]+e[i+1].f-e[i+1].t+e[i].t); } } } int m=10,sum=0; for(int i=1;i<=g;i++){ if(e[i].t-e[i-1].t>m){ printf("%d ",m+sum); return 0; } sum+=e[i].t-e[i-1].t; m-=e[i].t-e[i-1].t; m+=e[i].f; }printf("%d ",m+sum); return 0; }
本人期末考试已炸,714.5年级20多……和第八差3分……酸了……