多元Huffman編碼問題 貪心演算法

2021-10-10 18:59:17 字數 1783 閱讀 5586

在乙個操場的四周擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次至少選2 堆最多選k堆石子合併成新的一堆,合併的費用為新的一堆的石子數。試設計乙個演算法,計算出將n堆石子合併成一堆的最大總費用和最小總費用。

對於給定n堆石子,計算合併成一堆的最大總費用和最小總費用。

input

輸入資料的第1 行有2 個正整數n和k(n≤100000,k≤10000),表示有n堆石子,每次至少選2 堆最多選k堆石子合併。第2 行有n個數(每個數均不超過 100),分別表示每堆石子的個數。

output

將計算出的最大總費用和最小總費用輸出,兩個整數之間用空格分開。

sample input

7345

1312169

522

sample output

593

199

說明:

(1)求最大費用時只需將石堆排列後從大到小,兩兩進行合併即可。

(2)求最小費用時,將石堆排列後,每次合併的石堆數為k堆。但有時會出現特例,即每次合併k堆,最後一次合併時無法以k堆進行合併,這樣合併的結果就不是最小費用了。所以就要先判斷原總堆數是否能使每次合併的堆數都為k堆,如果不能的話就要在原堆數前面加上 x 個「0」堆來補齊缺少的堆數.。

例如共7堆最大合併5堆:

石子堆:45 13 12 5 9 22 16

這時排序後:5 9 12 13 16 22 45

如果先合併前5堆,這樣結果就為177

如果補零的話,得到 0 0 5 9 12 13 16 22 45,這時正好每次都合併5堆,最後合併為1堆,這時結果為148

(1)分別建立乙個遞增的優先佇列和乙個遞減的優先佇列。建立佇列的優點是可以對數字自動排序、取數等一些操作方便,如q.top();表示取隊首元素。

(2)對於遞增佇列:① 先判斷是否需要加「0」堆,需要就加;② 只要佇列中的元素個數大於1(等價於佇列中還至少有k堆石子,當然剩餘石子堆數為k的整數倍),就對佇列前k個元素進行處理。每次將隊首加入到sum中,加完後就把隊首彈出佇列,繼續處理下乙個隊首,直至處理了k個隊首(即合併了k堆石子)。得到n個sum後,將sum累加起來,得到的就是最小費用。

(3)對於遞減佇列:方法同二,只是這裡是連續處理2個隊首。

#include

using

namespace std;

intmain()

while

(q1.

size()

%(k-1)

!=1)//判斷q1能否每次合併k堆且恰好合併完

q1.push(0

);//不能合併完,就要壓入「0」

while

(q1.

size()

>1)

sum1+

=sum;

//將前k堆的費用加入到總費用中

q1.push

(sum)

;//這個前k堆的費用壓入佇列中

貪心 多元Huffman編碼問題

多元huffman編碼問題 time limit 1000 ms memory limit 65536 kib problem description 在乙個操場的四周擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次至少選2 堆最多選k堆石子合併成新的一堆,合併的費用為新的一堆的石子數。試設計...

1760多元Huffman編碼問題(貪心)

在乙個操場的四周擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次至少選2 堆最多選k堆石子合併成新的一堆,合併的費用為新的一堆的石子數。試設計乙個演算法,計算出將n堆石子合併成一堆的最大總費用和最小總費用。對於給定n堆石子,計算合併成一堆的最大總費用和最小總費用。輸入資料的第1 行有2 個正整...

多元Huffman編碼問題

problem description 在乙個操場的四周擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次至少選2 堆最多選k堆石子合併成新的一堆,合併的費用為新的一堆的石子數。試設計乙個演算法,計算出將n堆石子合併成一堆的最大總費用和最小總費用。對於給定n堆石子,計算合併成一堆的最大總費用和最...