4-19 多元Huffman编码问题
问题描述
在一个操场的四周摆放着 n 堆石子。现要将石子有次序地合并成一堆。规定每次至少选2 堆最多选 k 堆石子合并成新的一堆,合并的费用为新的一堆的石子数。试设计一个算法, 计算出将 n 堆石子合并成一堆的最大总费用和最小总费用。
对于给定 n 堆石子,编程计算合并成一堆的最大总费用和最小总费用。
数据输入:
第 1 行有 2 个正整数 n 和 k,表示有 n 堆石子,每次至少选 2 堆最多选 k 堆石子合并。第 2 行有 n 个数,分别表示每堆石子的个数。
Java
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
public class DuoYuanHuffmanBianMa {
private static int n,k;
private static int[] numbers;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
PriorityQueue<Integer> minQueue;
PriorityQueue<Integer> maxQueue;
while (true){
n = input.nextInt();
k = input.nextInt();
numbers = new int[n+1];
minQueue = new PriorityQueue<>(n);//默认升序
maxQueue = new PriorityQueue<>(n, Comparator.reverseOrder());//降序
for(int i=1; i<=n; i++){
numbers[i] = input.nextInt();
minQueue.add(numbers[i]);
maxQueue.add(numbers[i]);
}
int max = getMaxValueByQueue(maxQueue);
int min = getMinValueByQueue(minQueue);
System.out.println("Max: "+max);
System.out.println("Min: "+min);
}
}
//每次选k堆最小的,不足补0
private static int getMinValueByQueue(PriorityQueue<Integer> queue){
int i,j,m,t,sum,z;
m = (k-n%(k-1))%(k-1);
for(i=1,t=0; i<=k-m; i++)//补0
t += queue.poll();
sum = t;
z = (n-k+m)/(k-1);
queue.add(t);
for(i=1; i<=z; i++){
for(j=1,t=0; j<=k; j++)//每次选k堆最小的
t += queue.poll();
sum += t;
queue.add(t);
}
return sum;
}
//每次选2堆最大的
private static int getMaxValueByQueue(PriorityQueue<Integer> queue){
int sum = 0,temp;
for(int i=1; i<=n-1; i++){
temp = queue.poll() + queue.poll();
sum += temp;
queue.add(temp);
}
return sum;
}
}
Input & Output
7 3
45 13 12 16 9 5 22
Max: 593
Min: 199
Reference
王晓东《计算机算法设计与分析》(第3版)P135