【堆】B-Station

来源:互联网 发布:java毫秒转换成时分秒 编辑:程序博客网 时间:2024/05/16 17:59

B-Station

试题描述

在离著名的国家Berland不远的地方,有一个水下工作站。这个工作站有N层。已知:是第i层装有Wi的水,最多可以容纳Li的水,恐怖分子炸毁第i层的代价是Pi。第i层一旦被炸毁,该层所有的水都将倾泻到第i+1层。如果某一层的水量超过了它的容量(即Li),那么该层就将自动被毁坏,所有的水也会倾泻到下一层。

Pivland的恐怖分子想要用最少的钱毁掉第N层,现在他雇佣你来计算,需要炸毁哪些层。

输入

第一行有一个自然数N(1<=n<=15000)。接下来的N行,每行3个整数Wi, Li, Pi(0<=Wi,Li,Pi<=15000)。

输出

输出需要炸毁的层的编号。

样例

Input

3

1000 1000 1

0 1000 2

2 10 100

 

Output

1

2

=====================

=================

朴素

-------------------

type  node=record         w,l,p:longint;       end;var  n:longint;  ti:array[0..150000]of node;procedure init;begin  assign(input,'bstation.in');  assign(output,'bstation.out');  reset(input); rewrite(output);end;procedure terminate;begin  close(input); close(output);  halt;end;procedure main;var  i,j:longint;  ans,w,k:longint;  s:longint;begin  readln(n);  for i:=1 to n do    readln(ti[i].w,ti[i].l,ti[i].p);  ans:=ti[n].p; s:=n;  for i:=n-1 downto 1 do  //枚举从i开始炸    begin      k:=ti[i].p;      w:=ti[i].w;      if k>ans then continue;      for j:=i+1 to n do        begin          w:=w+ti[j].w;;          if w<=ti[j].l then            begin              k:=k+ti[j].p;              if k>ans then break;            end;        end;      if k<ans then        begin          ans:=k;          s:=i;        end;    end;  w:=ti[s].w;  writeln(s);  for i:=s+1 to n do    begin      w:=w+ti[i].w;      if w<=ti[i].l then writeln(i);    end;end;begin  init;  main;  terminate;end.


 

_________________________________

堆优化

---------------------------

var  n:longint;  sum,w,l,p:array[0..150000]of longint;  dui:array[0..150000]of longint;  dui_s:longint;  procedure init;begin  assign(input,'bstation.in');  assign(output,'bstation.out');  reset(input); rewrite(output);end;procedure terminate;begin  close(input); close(output);  halt;end;procedure shift(r,n:longint);var  k:longint;  tem:longint;begin  k:=2*r;  if (k+1<=n) and (sum[dui[k+1]]-l[dui[k+1]]>sum[dui[k]]-l[dui[k]])    then inc(k); //保证大根堆..  while (k<=n)and(sum[dui[k]]-l[dui[k]]>sum[dui[r]]-l[dui[r]]) do    begin      tem:=dui[k];      dui[k]:=dui[r];      dui[r]:=tem;      r:=k;      k:=2*r;      if (k+1<=n) and (sum[dui[k+1]]-l[dui[k+1]]>sum[dui[k]]-l[dui[k]])        then inc(k); //保证大根堆..    end;end;procedure adjust(r:longint);var  k:longint;  tem:longint;begin  k:=r shr 1;  while ((k>0) and (sum[dui[k]]-l[dui[k]]<sum[dui[r]]-l[dui[r]])) do  //保证上面的比较大..    begin      tem:=dui[k];      dui[k]:=dui[r];      dui[r]:=tem;      r:=k;      k:=r shr 1;    end;end;procedure main;var  i,j:longint;  ans:longint;  t:longint;  s:longint;  water:longint;begin  readln(n);  sum[0]:=0;  for i:=1 to n do    begin      readln(w[i],l[i],p[i]);      sum[i]:=sum[i-1]+w[i];    end;  ans:=p[n];  dui_s:=0;  inc(dui_s);  dui[dui_s]:=n;  //入堆  t:=ans;  for i:=n-1 downto 1 do    //表示从i开始炸.    begin      t:=t+p[i];  //记录变化{由上一次的状态而来}..      inc(dui_s);      dui[dui_s]:=i;      adjust(dui_s); //调整堆..      while sum[dui[1]]-l[dui[1]]>sum[i-1] do      //当不用炸的时侯        begin          t:=t-p[dui[1]];  //减去那个不需要炸得价值..          dui[1]:=dui[dui_s];          dec(dui_s);          shift(1,dui_s);        end;      if t<ans then        begin          ans:=t;          s:=i;        end;    end;  water:=w[s]; writeln(s);  for i:=s+1 to n do    begin      water:=water+w[i];      if water<=l[i] then writeln(i);    end;end;begin  init;  main;  terminate;end.

原创粉丝点击