二叉堆(一):基础

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

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.

你可能感兴趣的:(基础)