二叉堆(一):基础

原来对堆虽然理论比较了解但只打过几个堆排序,最近复习一下吧。

POJ3253

{
FJ要把一条木棒切成给定长度的n根木条,每次的花费是木棒的长度,求总花费

和合并果子基本一样,但是题目描述是逆向的,需要一点思考,可以把切割看成合并,贪心得合并最小的木条并记录最花费

虽然用队列是最优的,但就用来练习基本的heap操作吧,支持下滤,返回并删除最小元
2011-06-19 22:41
}



var
  a:array[0..1000000] of longint;
  heapsize:longint;
  m,n,min1,min2:longint;
  i,j,k:longint;
  ans:int64;

procedure heap_down(k:longint);
var
  i,x:longint;
begin
  x:=a[k];
  i:=k*2;
  while i<=heapsize do
  begin
    if (i<heapsize)and(a[i]>a[i+1]) then
      inc(i);
    if a[i]<x then
    begin
      a[k]:=a[i];
      k:=i;
      i:=i*2;
    end
    else break;
  end;
  a[k]:=x;
end;

procedure swap(var a,b:longint);
var
  c:longint;
begin
  c:=a;
  a:=b;
  b:=c;
end;

function get_min:longint;
var
  x:longint;
begin
  swap(a[1],a[heapsize]);
  dec(heapsize);
  heap_down(1);
  exit(a[heapsize+1]);
end;

procedure insert(key:longint);
var
  i:longint;
begin
  inc(heapsize);
  i:=heapsize;
  while a[i div 2]>key do
  begin
    a[i]:=a[i div 2];
    i:=i div 2;
  end;
  a[i]:=key;
end;

begin
  readln(n);
  for i:=1 to n do
    read(a[i]);
  heapsize:=n;
  for i:=heapsize div 2 downto 1 do
    heap_down(i);
  for i:=1 to  n-1 do
  begin
    min1:=get_min;
    min2:=get_min;
    inc(ans,min1+min2);
    insert(min1+min2);
  end;
  writeln(ans);
end.

POJ2051(WA的代码)

{
题意:输入N个任务编号和延时,每次执行任务后任务的延时会增加开始时的延时,按顺序输出前M个任务执行的编号(延时一样时按编号顺序)。

建一个小根堆。每次输出堆顶元素并增加堆顶元素关键字的值并下滤即可

不知为什么WA
2011-06-19 22:15
}
type
  data=record delay,time,num:longint end;
var
  a:array[0..100000] of data;
  i,j,k,m,n:longint;
  s:string[7];
  c:char;

procedure heap_down(k:longint);
var
  x:data;
  i:longint;
begin
  x:=a[k];
  i:=k*2;
  while i<=n do
  begin
    if (i<n) and ( (a[i].delay>a[i+1].delay) or
    ( (a[i].delay=a[i+1].delay) and (a[i].num>a[i+1].num) ) ) then
      inc(i);
    if x.delay>a[i].delay then
    begin
      a[k]:=a[i];
      k:=i;
      i:=i*2;
    end
    else break;
  end;
  a[k]:=x;
end;

procedure inc_key(k,add:longint);
begin
  inc(a[k].delay,add);
  heap_down(1);
end;

begin
  while not eof do
  begin
  n:=0;
  fillchar(a,sizeof(a),0);
  read(c);
  while c='R' do
  begin
    read(c,c,c,c,c,c,c);
    inc(n);
    readln(a[n].num,a[n].time);
    a[n].delay:=a[n].time;
    read(c);
  end;
  readln(m);
  for i:=n div 2  downto 1 do
    heap_down(i);
  for i:=1 to m do
  begin
    writeln(a[1].num);
    inc_key(1,a[1].time);
  end;
  end;
end.

posted on 2011-06-19 23:21  oa414  阅读(306)  评论(0编辑  收藏  举报

导航