P1156 垃圾陷阱

2018-06-17 22:32:21来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

题目描述

卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中。“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2<=D<=100)英尺。

卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。

每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。

假设卡门预先知道了每个垃圾扔下的时间t(0< t<=1000),以及每个垃圾堆放的高度h(1<=h<=25)和吃进该垃圾能维持生命的时间f(1<=f<=30),要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续10小时的能量,如果卡门10小时内没有进食,卡门就将饿死。

输入输出格式

输入格式:

第一行为2个整数,D 和 G (1 <= G <= 100),G为被投入井的垃圾的数量。

第二到第G+1行每行包括3个整数:T (0 < T <= 1000),表示垃圾被投进井中的时间;F (1 <= F <= 30),表示该垃圾能维持卡门生命的时间;和 H (1 <= H <= 25),该垃圾能垫高的高度。

输出格式:

如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。

输入输出样例

输入样例#1:
20 4
5 4 9
9 3 2
12 6 10
13 1 1
输出样例#1:
13

说明

[样例说明]

卡门堆放她收到的第一个垃圾:height=9;

卡门吃掉她收到的第二个垃圾,使她的生命从10小时延伸到13小时;

卡门堆放第3个垃圾,height=19;

卡门堆放第4个垃圾,height=20。

 

先将每一个垃圾按出现时间升序排序

定义a.x为出现时间a.h为高度a.t为吃下获得的血量

f[i][j]表示前i个垃圾在到达j的高度时剩余的最大血量

显而易见开始时f[0][0]为10

枚举一个i为垃圾编号j为高度,就有:

1.吃下这个垃圾f[i][j]=max{f[i][j],f[i-1][j]-(a[i].x-a[i-1].x)+a[i].t}

初始f[i][j]为-INF,a[i].x-a[i-1].x为从上一个垃圾到这一个垃圾要经过多少时间

而且显然要当f[i-1][j]-(a[i].x-a[i-1].x)>=0时才在当前时间是存活着的才可以吃下这个垃圾,吃下这个垃圾回复的血量就是a[i].t,且这只牛很厉害可以在刚好死的时候吃下一个垃圾(+1s)

2.将这个垃圾叠起来f[i][j]=max{f[i][j],f[i-1][j-a[i].h]-a[i].x+a[i-1].x}

在这种情况中显然我们如果可以将当前垃圾放置并达到j这个高度时在当前高度减去当前垃圾的高度a[i].h,即([j-a[i].h)要有一个可以在经过(a[i].x-a[i-1].x)的时间仍然存活,当然j-a[i].h要>=0,时间为负数显然是不可能的

而且这只牛很厉害,在生命的最后一秒仍然可以堆上一个垃圾(+1s)

这时如过我们枚举的高度j达到了目标高度n(要满足血量>=0)我们就可以直接输出a[i].x

为什么呢,因为开始时我们排了一次序,且我们是以每一个垃圾为外循环进行枚举的,所以当有一个j达到了目标高度那么肯定是最优的

当我们出了最优解后就可以直接退出了

但如果没有找到最优解,那我们就重新枚举一次此时的答案ans为max{ans,f[i][j]+a[i].x}

因为在到达了的i个垃圾后我们还可以再撑f[i][j]s

这样就可以了

实验证明,其实可以不用判断是否有负数高度或血量的情况(不知是不是数据水?)

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define INF 0x7f7f7f7f
 7 using namespace std;
 8 int deep,n;
 9 struct node
10 {
11     int t;// 时间 
12     int life;// 生命 
13     int h;// 能垫的高度 
14 }a[1001];
15 int comp(const node & a , const node & b)
16 {
17     return a.t<b.t;
18 }
19 int dp[1001][1001];
20 int main()
21 {
22     scanf("%d%d",&deep,&n);
23     for(int i=1;i<=n;i++)
24         scanf("%d%d%d",&a[i].t,&a[i].life,&a[i].h);
25         
26     for (int i=0;i<=n;i++)
27         for (int j=0;j<=deep;j++)
28             dp[i][j]=-INF;
29     
30     sort(a+1,a+n+1,comp);
31     dp[0][0]=10;
32     a[0].h=a[0].life=a[0].t=0;
33     int flag=0;
34     
35     for(int i=1;i<=n;i++)
36     {
37         for(int j=0;j<=deep;j++)
38         {
39             if(dp[i-1][j]-a[i].t+a[i-1].t>=0)
40             {
41                 dp[i][j]=max(dp[i][j],dp[i-1][j]-a[i].t+a[i-1].t+a[i].life);
42             }
43             if(dp[i-1][j-a[i].h]-a[i].t+a[i-1].t>=0&&j-a[i].h>=0)
44             {
45                 dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]-a[i].t+a[i-1].t);
46                 if(j==deep)
47                 {
48                     printf("%d",a[i].t);
49                     flag=1;
50                     return 0;
51                 }
52             }
53         }
54     }
55     int ans=0;
56     if(flag==0)
57     {
58         for(int i=0;i<=n;i++)
59         {
60             for(int j=0;j<=deep;j++)
61             {
62                 if(dp[i][j]!=INF)
63                 ans=max(ans,dp[i][j]+a[i].t);
64             }
65         }    
66     }
67     
68     printf("%d",ans);
69     return 0;
70 }

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:2105. [NOIP2015] 信息传递

下一篇:解决Boost库链接出错问题