L 樹 堆結構練習 合併果子之哈夫曼樹

2021-10-18 11:44:32 字數 2125 閱讀 8359

題目描述

在乙個果園裡,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。

每一次合併,多多可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經過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。

樣例

輸入

31 2 9

輸出15

提示

該題目用堆做,寫刪除函式時較為複雜,所以可以考慮優先佇列。

普通的佇列是一種先進先出的資料結構,元素在佇列尾追加,而從佇列頭刪除。

在優先佇列中,元素被賦予優先順序。當訪問元素時,具有最高優先順序的元素最先刪除。優先佇列具有最高端先出 (first in, largest out)的行為特徵。

優先佇列具有佇列的所有特性,包括佇列的基本操作,只是在這基礎上新增了內部的乙個排序,它本質是乙個堆實現的。

下面是優先佇列的使用方法

首先要包含標頭檔案

#include

```和佇列基本操作相同:

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

#include

using

namespace std;

const

int n=

100001

;int m=

0x3f3f3f3f

;int top[n]

;priority_queue<

int,vector<

int>

,greater<

int>

> q;

intmain()

int ans=0;

for(i=

0;i1;i++

) cout

}

樹 堆結構練習 合併果子之哈夫曼樹

在乙個果園裡,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。每一次合併,多多可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經過n 1次合併之後,就只剩下一堆了。多多在合併果子時總共消耗的體力等於每次合併所消耗體力之和...

樹 堆結構練習 合併果子之哈夫曼樹

time limit 1000ms memory limit 65536k 有疑問?點這裡 在乙個果園裡,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。每一次合併,多多可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經...

樹 堆結構練習 合併果子之哈夫曼樹

樹 堆結構練習 合併果子之哈夫曼樹 time limit 1000ms memory limit 65536k 在乙個果園裡,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。每一次合併,多多可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可...