ACM 懶省事的小明

OpenSoucre發表於2014-04-19

懶省事的小明

時間限制:3000 ms  |  記憶體限制:65535 KB
難度:3
 
描述
      小明很想吃果子,正好果園果子熟了。在果園裡,小明已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。小明決定把所有的果子合成一堆。 因為小明比較懶,為了省力氣,小明開始想點子了:
  每一次合併,小明可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經過n-1次合併之後,就只剩下一堆了。小明在合併果子時總共消耗的體力等於每次合併所耗體力之和。 
  因為還要花大力氣把這些果子搬回家,所以小明在合併果子時要儘可能地節省體力。假定每個果子重量都為1,並且已知果子的種類數和每種果子的數目,你的任務是設計出合併的次序方案,使小明耗費的體力最少,並輸出這個最小的體力耗費值。 
  例如有3種果子,數目依次為1,2,9。可以先將1、2堆合併,新堆數目為3,耗費體力為3。接著,將新堆與原先的第三堆合併,又得到新的堆,數目為12,耗費體力為12。所以小明總共耗費體力=3+12=15。可以證明15為最小的體力耗費值。
 
輸入
第一行輸入整數N(0<N<=10)表示測試資料組數。接下來每組測試資料輸入包括兩行,第一行是一個整數n(1<=n<=12000),表示果子的種類數。第二行包含n個整數,用空格分隔,第i個整數ai(1<=ai<=20000)是第i種果子的數目。
輸出
每組測試資料輸出包括一行,這一行只包含一個整數,也就是最小的體力耗費值。
樣例輸入
1
3 
1 2 9
樣例輸出
15
本題有點類似huffman編碼的前期步驟,每次選擇耗費體力最小的兩個值合併然後把合併後的值插入優先權佇列中
#include <iostream>
#include <queue>
#include <vector>

using namespace std;
struct cmp{
    bool operator()(long long  x,long long y){
        return x > y;
    }
};

int main(){
    int N;
    cin >>N;
    while(N--){
        int n ;
        cin >> n;
        priority_queue<long long,vector<long long>, cmp> p;
        for(int i = 0 ; i < n; ++ i){
            int a;
            cin >> a;
            p.push(a);
        }
        long long sum = 0;
        while(p.size()>1){
            long x = p.top();p.pop();
            long y = p.top();p.pop();
            sum +=(x+y);
            p.push(x+y);
        }
        p.pop();
        cout<<sum<<endl;

    }
}