(ssl1673、1845)垃圾陷阱

垃圾陷阱

Description

卡门——农夫约翰极其珍视的一条Holsteins奶牛——已经落了到“垃圾井”中。“垃圾井”是农夫们扔垃圾的地方,它的深度为D (2 <= D <= 100)英尺。
卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。
每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。
假设卡门预先知道了每个垃圾扔下的时间t(0

Input

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

Output

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

Sample Input

20 4
5 4 9
9 3 2
12 6 10
13 1 1

Sample Output

13
[样例说明]
卡门堆放她收到的第一个垃圾:height=9;
卡门吃掉她收到的第二个垃圾,使她的生命从10小时延伸到13小时;
卡门堆放第3个垃圾,height=19;
卡门堆放第4个垃圾,height=20。

Source

elba

题解:

   本题是dp,但并没有明显的动态转移方程(数组v[i,j]表示当垃圾堆到i高度时奶牛是否存活)像01背包,但这题不装是堆起来,装是吃掉
   首先我们要预处理,v[0,10]为true(题目说卡门一开始就能活10小时)。接着,我们要按t[i]来排序(输入并不是有序的,万一卡门活不到下一个垃圾来呢?)然后我们就可以开心地枚举了!
   k枚举1~g,标记吃掉第k个垃圾后能话多久(为卡门出不去,只吃垃圾的输出做准备,好惨啊(´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥`)
   i枚举高度,在当前高度如果活得下来的情况下,如果i堆上第k个垃圾时就能出去就直接输出,再当机就可以了
   j枚举活的小时,为什么我们不用最大小时数去算呢?因为最大小时数就是把全部垃圾都吃掉,这样就出不去了!而且假设你吃了x垃圾能活10个小时,那么你吃了x也一定能活9个小时啊!所以我们可以只吃x,接着把前面的点更新得更优(就是在v[i,j]中,保持j不变,把i变大)
   如果奶牛出不去的话就用奶牛吃掉所有垃圾存活的时间+10来downto(为什么不直接输出呢?因为万一卡门活不到下一个垃圾来呢?)

var
 v:array[0..100,0..3000]of boolean;
 t,f,h:array[0..100]of longint;
 d,g,l,i,j,k:longint;
begin
 read(d,g);
 l:=10;
 for i:=1 to g do
  begin
   read(t[i],f[i],h[i]);
   l:=l+f[i];//理论上的最大存活时间 (可惜现实中你可能等不到了)
  end;
 for i:=1 to g-1 do//排序
  for j:=i+1 to g do
   if t[i]>t[j] then
    begin
     t[0]:=t[i];t[i]:=t[j];t[j]:=t[0];
     f[0]:=f[i];f[i]:=f[j];f[j]:=f[0];
     h[0]:=h[i];h[i]:=h[j];h[j]:=h[0];
    end;
 v[0,10]:=true;
 for k:=1 to g do
  for i:=d-1 downto 0 do
   for j:=l downto t[k] do
    if v[i,j] then//活得到当前时间
     begin
      v[i+h[k],j]:=true;//堆起来的情况
      if i+h[k]>=d then//堆起来,且爬出去的情况
       begin
        writeln(t[k]);
        halt;
       end;
      v[i,j+f[k]]:=true;//吃掉的情况
     end;
 for i:=l downto 0 do
  if v[0,i] then
             begin
              writeln(i);
              break;
             end;
end.

你可能感兴趣的:(竞赛(测试)题)