垃圾陷阱
洛谷题号:P1156
出处: ?
主要算法:DP-背包问题
难度:4.6
https://www.luogu.org/problemnew/show/P1156
思路分析:
背包:很显然对于每个垃圾,可以选择吃或者垫。(显然不会去选择不管)。
令f[i][j]表示前i个垃圾,高度为j时的最大生命值。值得注意的是,因为垃圾是按照一定时间顺序的,所以当高度第一次大于等于深度时就一定是最早的时刻。这一点在DP过程中就可以完美解决了。
f[0][0]=10(已知)
我们每一次都考虑i+1个垃圾的情况。而对于第i+1个垃圾的操作,首先需要保证的是我们能够活到i+1个垃圾掉下来的时候。而能否活下来取决于现在到下一个垃圾之间的时间,也就是a[i+1].t – a[i].t。在能够活下来的前提下,我们很容易写出方程。
*f数组保证最大生命值,有没有可能生命值不是最大的时候会更早跳出洞?
因为是否能跳出是对于每一个物品在高度循环里判断的,所以应当考虑到所有高度的可能性。而这与时间是完全没有关系的,只有当前的j满足跳出洞的高度,并且可以支撑到j,便可以选择跳出。而为了能尽量支撑到那时候,所以要让生命值尽量大。至于选择哪个高度,因为在i的循环体里,所以时间都是一样的。进一步思考,其实答案的时间应该都在各个垃圾进入的时间点之中。
解决了第一个子问题,也就是能够跳出的情况,继续分析跳不出怎么办。既然跳不出,还想活得最久。那么破罐子破摔,把所有垃圾都吃了,省得浪费,这样能够活最久。所以判断出无法跳出以后,循环一下重新模拟即可。
代码注意点:
题目并没有将垃圾按时间顺序帮我们排好序(样例有毒),所以别忘了sort。并且注意,刚开始memset(-1)。
F数组之所以要赋值成一个负数,是因为当f[i][j]=0时奶牛依然可以进行操作,也就是说,奶牛并没有死!
1 // luogu-judger-enable-o2 2 /*This Program is written by QiXingZhi*/ 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstring> 6 #define N (100010) 7 #define ll long long 8 #define INF (0x7f7f7f7f) 9 #define read(x) x=Rd() 10 #define Max(a,b) (((a) > (b)) ? (a) : (b)) 11 #define Min(a,b) (((a) < (b)) ? (a) : (b)) 12 #define FILE_IN(x) freopen(x".in","r",stdin) 13 using namespace std; 14 inline int Rd(){ 15 char c = getchar(); int x = 0;int w = 1; 16 while(c ^ '-' && (c < '0' || c > '9')) c=getchar(); 17 if(c == '-') w = -1, c = getchar(); 18 while(c >= '0' && c <= '9') x = (x<<3)+(x<<1)+c-48,c = getchar(); 19 return x * w; 20 } 21 struct Rubbish{ 22 int t,f,h; 23 }a[110]; 24 int d,g,ans,tmp=10; 25 int f[110][3010]; 26 inline bool comp(Rubbish& a, Rubbish& b){ 27 return a.t < b.t; 28 } 29 int main(){ 30 // FILE_IN(); 31 memset(f,-1,sizeof(f)); 32 read(d),read(g); 33 for(int i = 1; i <= g; ++i){ 34 read(a[i].t); 35 read(a[i].f); 36 read(a[i].h); 37 } 38 sort(a+1,a+g+1,comp); 39 f[0][0] = 10; 40 for(int i = 0; i < g; ++i){ 41 for(int j = 0; j <= d; ++j){ 42 if(f[i][j] < 0) continue; 43 if(f[i][j]>=a[i+1].t-a[i].t && j+a[i+1].h>=d){ 44 printf("%d",a[i+1].t); 45 return 0; 46 } 47 if(f[i][j]>=a[i+1].t-a[i].t){ 48 f[i+1][j+a[i+1].h] = Max(f[i+1][j+a[i+1].h],f[i][j]-a[i+1].t+a[i].t); 49 f[i+1][j] = Max(f[i+1][j], f[i][j] + a[i+1].f - a[i+1].t + a[i].t); 50 } 51 } 52 } 53 for(int i = 1; i <= g; ++i){ 54 if(a[i].t-a[i-1].t > tmp){ 55 printf("%d",a[i-1].t+tmp); 56 return 0; 57 } 58 tmp += a[i].f-(a[i].t-a[i-1].t); 59 } 60 printf("%d",a[g].t+tmp); 61 return 0; 62 }
2018-05-08 21:38:49