多元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......

多元Huffman编码问题-优先队列_第1张图片

#include

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 = "<
      sum2 += sum;
      //cout<<"sum2 = "<
      q2.push(sum);
  }
  cout<<sum2<<" "<<sum1<<endl;
  return 0;
}

你可能感兴趣的:(多元Huffman编码问题-优先队列)