思想与合并果子相同。逆序地来想,显然这些板子必须一共切割n-1次,如何恰当的分配这n-1次切割就是关键所在。这里就用到了构造Huffman树的贪心思想。
即每次从待合并序列中取两个最小的值,将它们合并成一个较大的,然后把这个较大的在加入进待合并的序列当中,直到待合并序列中只有一个元素。而不加任何优化时复杂度为O(n^2),难以承受。
可以用堆将复杂度优化到O(nlogn),就完全可以接受了。
CODE
Program plank;//By_Thispoet Const maxn=20000; Var i,j,k,m,n,heap_size :Longint; ans :Int64; heap :Array[1..maxn]of Longint; Procedure Down(i:Longint); var j:Longint; begin while (i<<1)<=heap_size do begin j:=i<<1; if (heap[j+1]<heap[j])and(j<heap_size) then inc(j); if heap[j]<heap[i] then begin heap[i]:=heap[i] xor heap[j]; heap[j]:=heap[i] xor heap[j]; heap[i]:=heap[i] xor heap[j]; i:=j; end else break; end; end; Procedure Up(i:Longint); var j:Longint; begin while i>1 do begin j:=i>>1; if heap[j]>heap[i] then begin heap[i]:=heap[i] xor heap[j]; heap[j]:=heap[i] xor heap[j]; heap[i]:=heap[i] xor heap[j]; i:=j; end else break; end; end; BEGIN readln(heap_size); for i:=1 to heap_size do readln(heap[i]); for i:=heap_size >>1 downto 1 do Down(i); while heap_size>1 do begin k:=heap[1]; heap[1]:=heap[heap_size]xor heap[1]; heap[heap_size]:=heap[heap_size]xor heap[1]; heap[1]:=heap[heap_size]xor heap[1]; dec(heap_size); Down(1); inc(k,heap[1]); heap[1]:=heap[heap_size]xor heap[1]; heap[heap_size]:=heap[heap_size]xor heap[1]; heap[1]:=heap[heap_size]xor heap[1]; dec(heap_size); Down(1); inc(heap_size); heap[heap_size]:=k; Up(heap_size); inc(ans,k); end; writeln(ans); END.