题目大意:一头奶牛掉进了深度为d的坑里,现在有g个垃圾在特定时刻ti扔进来。奶牛可以吃垃圾以获得体力,吃第i个垃圾能获得mi的体力,也可以堆放垃圾以逃生,第i个垃圾高度为hi。当高度≥d时奶牛成功逃生。但当体力值小于0时逃生失败(每一个单位时间耗费一点体力)。
现在奶牛初始体力值为10,问:如果能逃生,最短什么时候;如果不能,最长能活多久?
解题思路:动态规划。
设dp[i][j]表示到第i个垃圾扔下来的时候,已经堆到j的高度时,奶牛剩余的最大体力。则
$dp[i][j]=max(dp[i][j-h[i]]-(t[i]-t[i-1])(当dp[i][j-h[i]]-(t[i]-t[i-1])geq 0时),dp[i][j]-(t[i]-t[i-1])+m[i](当dp[i][j]-(t[i]-t[i-1])geq 0时))$。
每次判断dp[i][d]是否≥0,如果是,则t[i]就是答案。
如果dp完后还未得出答案,说明无法逃生,则贪心求出能活的最长时间即可(即扔进来的垃圾全吃了,到饿死为止)。
注意按照投入时刻进行排序。
时间复杂度$O(dg)$。
C++ Code:
#include<cstdio> #include<cstdarg> #include<cctype> #include<algorithm> #include<cstring> using namespace std; int d,n,dp[102][25005]; struct brush{ int t,m,h; bool operator <(const brush& rhs)const{return t<rhs.t;} }a[102]; inline int readint(){ char c=getchar(); bool b=false; for(;!isdigit(c);c=getchar())b=c=='-'; int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); return b?-d:d; } inline void read(int cnt,...){ va_list arg_ptr; va_start(arg_ptr,cnt); for(int i=0;i<cnt;++i){ int* p=va_arg(arg_ptr,int*); *p=readint(); } } int main(){ read(2,&d,&n); for(int i=1;i<=n;++i)read(3,&a[i].t,&a[i].m,&a[i].h); sort(a+1,a+n+1); memset(dp,170,sizeof dp); dp[0][0]=10; a[0].t=0; for(int i=1;i<=n;++i){ int tcha=a[i].t-a[i-1].t; for(int j=0;j<=d;++j){ if(dp[i-1][j]-tcha>=0) dp[i][j]=max(dp[i][j],dp[i-1][j]-tcha+a[i].m); if(j>=a[i].h) if(dp[i-1][j-a[i].h]-tcha>=0) dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]-tcha); } if(dp[i][d]>=0){ printf("%d ",a[i].t); return 0; } } int hp=10; for(int i=1;i<=n;++i){ if(hp>=a[i].t)hp+=a[i].m;else{ printf("%d ",hp); return 0; } } printf("%d ",hp); return 0; }