在一個果園裏,多多已經將全部的果子打了下來,並且按果子的不一樣種類分紅了不一樣的堆。多多決定把全部的果子合成一堆。ios
每一次合併,多多能夠把兩堆果子合併到一塊兒,消耗的體力等於兩堆果子的重量之和。能夠看出,全部的果子通過n-1次合併以後,就只剩下一堆了。多多在合併果子時總共消耗的體力等於每次合併所耗體力之和。ui
由於還要花大力氣把這些果子搬回家,因此多多在合併果子時要儘量地節省體力。假定每一個果子重量都爲1,而且已知果子的種類數和每種果子的數目,你的任務是設計出合併的次序方案,使多多耗費的體力最少,並輸出這個最小的體力耗費值。spa
例若有3種果子,數目依次爲1,2,9。能夠先將一、2堆合併,新堆數目爲3,耗費體力爲3。接着,將新堆與原先的第三堆合併,又獲得新的堆,數目爲12,耗費體力爲12。因此多多總共耗費體力=3+12=15。能夠證實15爲最小的體力耗費值。設計
輸入格式:code
輸入文件fruit.in包括兩行,第一行是一個整數n(1<=n<=10000),表示果子的種類數。第二行包含n個整數,用空格分隔,第i個整數ai(1<=ai<=20000)是第i種果子的數目。blog
輸出格式:string
輸出文件fruit.out包括一行,這一行只包含一個整數,也就是最小的體力耗費值。輸入數據保證這個值小於2^31。it
3 1 2 9
15
對於30%的數據,保證有n<=1000:io
對於50%的數據,保證有n<=5000;class
對於所有的數據,保證有n<=10000。
從這個問題能夠深挖出神奇的哈夫曼樹問題。
由於這題裏合併的是二叉樹,因此結點數量什麼的都不用考慮。用堆維護數據,每次貪心取兩個最小的合併便可(由於要使大數被累加的次數儘可能少)
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 #define LL long long 9 using namespace std; 10 priority_queue <long long,vector<long long>,greater<long long> >q; 11 LL ans; 12 int n; 13 int main(){ 14 scanf("%d",&n); 15 int i,j; 16 LL x; 17 for(i=1;i<=n;i++){ 18 scanf("%lld",&x); 19 q.push(x); 20 } 21 for(i=1;i<n;i++){ 22 LL tmp=q.top();q.pop(); 23 tmp+=q.top();q.pop(); 24 q.push(tmp); 25 ans+=tmp; 26 } 27 printf("%lld\n",ans); 28 return 0; 29 }