多元Huffman編碼問題-優先隊列

多元Huffman編碼問題
Time Limit: 1000 ms Memory Limit: 65536 KiB

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

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

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

Sample Input

7 3
45 13 12 16 9 5 22

Sample Output

593 199

這裏用到優先隊列,自行學習
優先隊列 priority_queue 詳解

求最大費用時只需將石堆排列後從大到小,兩兩進行合併即可
求最小費用時,將石堆排列後,要儘可能的合併最少的次數且每次合併的石堆數爲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,每次合併K堆,結果爲148

例題,排序5, 9, 12, 13, 16, 22, 45

最小:
判斷是否需要添加0,不需要,進入加和,5 + 9 + 12 = 26;sum1 = 26,26進隊;
13, 16, 22,26, 45;13 + 16 + 22 = 51;sum1 = 26 + 51 = 77,51進隊;
26, 45, 51,26 + 45 + 51 = 122;sum1 = 77 + 122 = 199,結束。
最大:
45, 22, 16, 13, 12, 9, 5 ;
45 + 22 = 67;sum = 67,sum2 = 67,67進隊;
67 + 16 = 83;sum = 67 + 16 = 83;sum2 = 83 + 67 = 150;150進隊;
83 + 13 = 96;sum = 96 + 150 = 246......

在這裏插入圖片描述

#include<bits/stdc++.h>

using namespace std;

int main()
{
  int n, k;
  cin>>n>>k;
  priority_queue<int, vector<int>, greater<int> > q1;///greater是從小到大
  priority_queue<int, vector<int>,less<int> >q2;///less是從大到小

  for(int i = 0; i < n; i++)
  {
      int x;
      cin>>x;
      q1.push(x);
      q2.push(x);
  }
  long long sum1 = 0, sum2  = 0;
  while(q1.size() % (k - 1) != 1)
      q1.push(0);///添加0
  while(q1.size() > 1)
  {
      long long sum = 0;
      for(int i = 0; i < k; i++)
      {
          sum += q1.top();
          q1.pop();
      }
      sum1 += sum;
      q1.push(sum);
  }
  while(q2.size() > 1)
  {
      long long sum = 0;
      int a = q2.top();
      q2.pop();
      int b = q2.top();
      q2.pop();
      sum += (a + b);
      //cout<<"sum = "<<sum<<endl;
      sum2 += sum;
      //cout<<"sum2 = "<<sum<<endl;
      q2.push(sum);
  }
  cout<<sum2<<" "<<sum1<<endl;
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章