[NOIP2004] 提升組 洛谷P1090 合併果子

 

題目描述

在一個果園裏,多多已經將全部的果子打了下來,並且按果子的不一樣種類分紅了不一樣的堆。多多決定把全部的果子合成一堆。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

 

輸入輸出樣例

輸入樣例#1:
3 
1 2 9 
輸出樣例#1:
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 }
相關文章
相關標籤/搜索