懶省事的小明 時間限制: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
Code:
題意不難理解,每次取最小的兩個即可
重點是用到了優先隊列,大家說用這個效率不太高,但是可以少寫很多代碼類
下面是優先隊列的用法~
在優先隊列中,優先順序高的元素先出隊列。
標準庫預設使用元素類型的<操作符來確定它們之間的優先順序關係。
優先隊列的第一種用法,也是最常用的用法:
priority_queue<int> qi;
通過<操作符可知在整數中元素大的優先順序高。
第二種方法:
在樣本1中,如果我們要把元素從小到大輸出怎麼辦呢?
這時我們可以傳入一個比較函數,使用functional.h函數對象作為比較函數。這是編譯器中的預設比較函數
priority_queue<int, vector<int>, greater<int> >qi2;
其中
第二個參數為容器類型。
第二個參數為比較函數。
第三種方法:
自訂優先順序。friend為友元函數
struct node
{
friend bool operator< (node n1, node n2)
{
return n1.priority < n2.priority;
}
int priority;
int value;
};
在該結構中,value為值,priority為優先順序。
通過自訂operator<操作符來比較元素中的優先順序。
但如果結構定義如下:
struct node
{
friend bool operator> (node n1, node n2)
{
return n1.priority > n2.priority;
}
int priority;
int value;
};
則會編譯不過(G++編譯器)
因為標準庫預設使用元素類型的<操作符來確定它們之間的優先順序關係。
而且自訂類型的<操作符與>操作符並無直接聯絡,故會編譯不過。
常用的操作如下:
empty() 如果優先隊列為空白,則返回真
pop() 刪除第一個元素
push() 加入一個元素
size() 返回優先隊列中擁有的元素的個數
top() 返回優先隊列中有最高優先順序的元素
但是在使用時必須注意:priority_queue放置元素時,不會判斷元素是否重複。(因為在模板的第二個參數時順序容器,不能保證元素的唯一性)
在自己實現Compare函數(函數對象)時,函數對象是中的參數如果是const類型,那麼隊列存放的元素(比如Node)的比較函數也一定要實現為const。
因為函數對象在執行時通過其參數調用Node的比較函數
55題代碼:
#include<stdio.h>#include<queue>using namespace std;priority_queue<long long,vector<long long>,greater<long long> >fr;int main(){int t,n,i;long long sum,w,m1,m2;scanf("%d",&t);while(t--){scanf("%d",&n);for(i=0;i<n;i++){scanf("%lld",&w);fr.push(w);}sum = 0;while(fr.size()>1){m1 = fr.top();fr.pop();m1 += fr.top();fr.pop();sum += m1;fr.push(m1);}fr.pop();printf("%lld\n",sum);}return 0;}