合併果子

題目描述

在一個果園裏,多多已經將全部的果子打了下來,並且按果子的不一樣種類分紅了不一樣的堆。多多決定把全部的果子合成一堆。ios

每一次合併,多多能夠把兩堆果子合併到一塊兒,消耗的體力等於兩堆果子的重量之和。能夠看出,全部的果子通過n-1次合併以後,就只剩下一堆了。多多在合併果子時總共消耗的體力等於每次合併所耗體力之和。ide

由於還要花大力氣把這些果子搬回家,因此多多在合併果子時要儘量地節省體力。假定每一個果子重量都爲1,而且已知果子的種類數和每種果子的數目,你的任務是設計出合併的次序方案,使多多耗費的體力最少,並輸出這個最小的體力耗費值。ui

例若有3種果子,數目依次爲1,2,9。能夠先將一、2堆合併,新堆數目爲3,耗費體力爲3。接着,將新堆與原先的第三堆合併,又獲得新的堆,數目爲12,耗費體力爲12。因此多多總共耗費體力=3+12=15。能夠證實15爲最小的體力耗費值。spa

輸入輸出格式

輸入格式:設計

輸入文件fruit.in包括兩行,第一行是一個整數n(1<=n<=10000),表示果子的種類數。第二行包含n個整數,用空格分隔,第i個整數ai(1<=ai<=20000)是第i種果子的數目。3d

輸出格式:code

輸出文件fruit.out包括一行,這一行只包含一個整數,也就是最小的體力耗費值。輸入數據保證這個值小於2^31。blog

輸入輸出樣例

輸入樣例#1: 隊列

3ip

1 2 9

輸出樣例#1: 

15

說明

對於30%的數據,保證有n<=1000:

對於50%的數據,保證有n<=5000;

對於所有的數據,保證有n<=10000。

noip2004提升組第2

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

講解:

對於這題,關鍵是它的合併順序,先看一個數列:咱們假設有n個數a1,a2,a3,...,anan開始按題目合併

a1,a2,a3,...,an-1+an   

a1,a2,a3,...,an-2+an-1+an   

...

a1+a2+a3+...an

這樣耗費體力值:an*(n-1)+an-1*(n-1)+an-2*(n-2)+an-3*(n-3)+...+a1*1因此當每次合併都合併最小的數時,耗費的體力值才能最小。

思路出來了,可怎樣實現呢?用每次都要找最小和次小On)顯然不划算,咱們能夠用STL的優先隊列(堆)priority_queue來實現(也能夠手打或push_heap和pop_heap)。

代碼實現:

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>//優先隊列的頭文件 
using namespace std;
priority_queue<int> q;//優先隊列 
int n,ans,k,i,a,b;
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&k);
        q.push(-k);//存成負數,由於STL默認大頂堆。 
    }
    while(--n)//n-1次 
    {
        a=-q.top();q.pop();
        b=-q.top();q.pop();//取兩個最小的數 
        q.push(-a-b);//合併 
        ans+=a+b;
    }
    cout<<ans;
    return 0;
}
View Code
相關文章
相關標籤/搜索