多元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;
}

浙公网安备 33010602011771号