題目描述
有一棵無窮大的滿二叉樹,根為start,其餘所有點的權值為點到根的距離,
現在你有一些撲克牌,點數從1到13,你要把這些撲克牌全部放到這個樹上:
1. 當你把點數為i的撲克牌放在權值為j的點上,那麼你會得到i*j的分數。
2. 當你把一個撲克牌放在一個節點上,那麼你就不能把別的撲克牌放在這個節點以及這個節點的子樹上。
你的目標是最小化你的得分。
輸入
輸入第一行為一個數字N,表示你有的撲克牌數;
接下來一行N個數字,數字在1到13之間。
輸出
一行一個整數,表示你的最小得分
範例輸入
3 5 10 13
範例輸出
43
提示
資料範圍:
30%資料 N<=100
100%資料滿足1<=N<=10000
範例說明:
分析就略過了。。
合并果子是經典題目吧。。。。
開始其實沒看出來是合并果子。。。。
後來才發現。
我的方法是快排+插排。就這樣。
var i,j:longint; ans,n,m,k,l,bb:int64; a:array[0..30000]of int64; procedure sort(l,r:longint); var i,j,x:longint; begin i:=l;j:=r; x:=a[(l+r)>>1]; repeat while a[i]<x do inc(i); while a[j]>x do dec(j); if i<=j then begin a[0]:=a[i];a[i]:=a[j];a[j]:=a[0]; inc(i);dec(j); end; until i>j; if i<r then sort(i,r); if l<j then sort(l,j); end; begin readln(n); a[n+1]:=maxlongint*10000000; for i:=1 to n do read(a[i]); sort(1,n); for i:=2 to n-1 do begin a[i]:=a[i]+a[i-1]; ans:=ans+a[i]; for j:=i+1 to n+1 do if (a[i]<a[j])and(a[i]>=a[j-1]) then begin bb:=j-1;break;end; k:=a[i]; for j:=i to bb-1 do a[j]:=a[j+1]; a[bb]:=k; end; writeln(ans+a[n-1]+a[n]); end.