垃圾陷阱

垃圾陷阱

洛谷题号: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

猜你喜欢

转载自www.cnblogs.com/qixingzhi/p/9194703.html