L - 樹-堆結構練習——合并果子之哈夫曼樹
題目鏈接: link.
題目描述
在一個果園里,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆,多多決定把所有的果子合成一堆,
每一次合并,多多可以把兩堆果子合并到一起,消耗的體力等于兩堆果子的重量之和,可以看出,所有的果子經過n-1次合并之后,就只剩下一堆了,多多在合并果子時總共消耗的體力等于每次合并所消耗體力之和,
因為還要花大力氣把這些果子搬回家,所以多多在合并果子時要盡可能地節省體力,假定每個果子重量都為1,并且已知果子的種類數和每種果子的數目,你的任務是設計出合并的次序方案,使多多耗費的體力最少,并輸出這個最小的體力耗費值,
例如有3種果子,數目依次為1,2,9,可以先將1、2堆合并,新堆數目為3,耗費體力為3,接著,將新堆與原先的第三堆合并,又得到新的堆,數目為12,耗費體力為12,所以多多總共耗費體力=3+12=15,可以證明15為最小的體力耗費值,
輸入
第一行是一個整數n(1<=n<=10000),表示果子的種類數,第二行包含n個整數,用空格分隔,第i個ai(1<=ai<=20000)是第i個果子的數目,
輸出
輸出包括一行,這一行只包含一個整數,也就是最小的體力耗費值,輸入資料保證這個值小于2^31,
樣例
輸入
3
1 2 9
輸出
15
提示
該題目用堆做,寫洗掉函式時較為復雜,所以可以考慮優先佇列,
普通的佇列是一種先進先出的資料結構,元素在佇列尾追加,而從佇列頭洗掉,
在優先佇列中,元素被賦予優先級,當訪問元素時,具有最高優先級的元素最先洗掉,優先佇列具有最高級先出 (first in, largest out)的行為特征,
優先佇列具有佇列的所有特性,包括佇列的基本操作,只是在這基礎上添加了內部的一個排序,它本質是一個堆實作的,
下面是優先佇列的使用方法
首先要包含頭檔案
#include<queue>
```和佇列基本操作相同:
top() 訪問隊頭元素
empty() 佇列是否為空
size() 回傳佇列內元素個數
push() 插入元素到隊尾 (并排序)
emplace() 原地構造一個元素并插入佇列
pop() 彈出隊頭元素
swap ()交換內容
priority_queue<int,vector<int>,greater<int> > q;//定義小頂堆
priority_queue<int,vector<int>,less<int> > q;//定義大頂堆
priority_queue<int>//默認為定義的大頂堆
//greater和less是std實作的兩個仿函式(就是使一個類的使用看上去像一個函式,其實作就是類中實作一個operator(),這個類就有了類似函式的行為,就是一個仿函式類了)
下面是這道題用優先佇列的解法
#include<bits/stdc++.h>
#include<queue>
using namespace std;
const int N=100001;
int M=0x3f3f3f3f;
int top[N];
priority_queue<int,vector<int>,greater<int> > q;
int main()
{
int n,i,j,y,z;
cin>>n;
for(i=0;i<n;i++)
{
int x;
cin>>x;
q.push(x);
}
int ans=0;
for(i=0;i<n-1;i++)
{
y=q.top();
q.pop();
z=q.top();
q.pop();
q.push(y+z);
ans=ans+y+z;
}
cout<<ans<<endl;
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/255307.html
標籤:其他
上一篇:如何使用C++做個簡單推箱子游戲
