在乙個操場的四周擺放著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堆石子,計算合併成一堆的最大總費用和最...