多元Huffman编码问题—贪心

一、问题描述

描述

在一个操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次至少选2 堆最多选k堆石子合并成新的一堆,合并的费用为新的一堆的石子数。试设计一个算法,计算出将n堆石子合并成一堆的最大总费用和最小总费用。 对于给定n堆石子,计算合并成一堆的最大总费用和最小总费用。

输入

输入数据的第1 行有2 个正整数n和k(n≤100000,k≤10000),表示有n堆石子,每次至少选2 堆最多选k堆石子合并。第2 行有n个数,分别表示每堆石子的个数。

输出Output

将计算出的最大总费用和最小总费用输出,两个整数之间用空格分开。

Sample Input

7 3
45 13 12 16 9 5 22

Sample Output

593 199

问题分析

  • 最大值是每次取数量最大的两堆合并,然后把合并的数记录下来,然后放回数组种
  • 最小值是除第一次外每次取K个最小的合并,然后把合并的放回数组,递归调用。除去第一次每次都取K个是因为要保证最后一次取到K个数据

代码

#include<iostream>
#include<algorithm>
using namespace std;

int n,k;
int p[200000];
/**
把数组P中的第n-1个数据,插入到i到n-2数据里,
相当于把i到n从小到大排序
*/
void my_sorted(int i){
    for (int j = n-1; j >= i; --j) {
        if(p[j]<p[j-1]){
            swap(p[j],p[j-1]);
        }
        else
            break;
    }
}

int main(){
    cin>>n>>k;
    for (int i = 0; i < n; ++i) {
        cin>>p[i];
    }
    //扩大数组,保证每次都能取K个数据
    while(n%(k-1)!=1)
        p[n++]=0;
    //从小到大排序
    sort(p,p+n);

    //计算最大值
    int max = 0;
    int max2 = p[n-1];
    for(int i=n-2;i>=0;i--){
        if(p[i] == 0)
            break;
        max2 += p[i];
        max += max2;
    }

    //计算最小值
    int min = 0;
    for (int i = 0; i < n-1;) {
        int min2 = 0;
        for (int j = 0; j < k; ++j) {
            min2 += p[i++];
        }
        p[n++] = min2;
        min += min2;
        my_sorted(i);

//        for (int j = i; j < n; ++j) {
//            cout<<p[j]<<' ';
//        }
//        cout<<endl;
    }
    cout<<max<<' '<<min<<endl;
}

posted @ 2020-11-27 16:09  陈葛杰  阅读(532)  评论(0)    收藏  举报