南邮 OJ 1267 多元Huffman编码问题

多元Huffman编码问题

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 93            测试通过 : 14 

比赛描述

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

对于给定n堆石子,编程计算合并成一堆的最大总费用和最小总费用。



输入

文件的第1 行有2 个正整数n和k,表示有n堆石子,每次至少选2 堆最多选k堆石子合并。第2 行有n个数,分别表示每堆石子的个数。

输出

程序运行结束时,将计算出的最大总费用和最小总费用输出。

样例输入

7 3
45 13 12 16 9 5 22

样例输出

593 199

提示

undefined

题目来源

NUAA



/*87 MS
#include<iostream>
#include<set>
using namespace std;

int main(){
//	freopen("test.txt","r",stdin);
	int n,k,i,num,cost;
	multiset<int> iSet1,iSet2;
	multiset<int>::iterator it;
	multiset<int>::reverse_iterator rIt;
	scanf("%d%d",&n,&k);
	for(i=0;i<n;i++){
		scanf("%d",&num);
		iSet1.insert(num);
		iSet2.insert(num);
	}
	cost = 0;
	while(!iSet1.empty()){
		num = 0;
		rIt = iSet1.rbegin();
		for(i=0; !iSet1.empty() && i<2; i++){
			rIt = iSet1.rbegin();
			num += *rIt;
			iSet1.erase((++rIt).base());
		}
		if(iSet1.size()){
			iSet1.insert(num);
		}
		cost += num;
	}
	printf("%d ",cost);

	cost = 0;
	while(iSet2.size() % (k-1) != 1){
		iSet2.insert(0);
	}
	while(!iSet2.empty()){
		num = 0;
		it = iSet2.begin();
		for(i=0; !iSet2.empty() && i<k; i++){
			it = iSet2.begin();
			num += *it;
			iSet2.erase(it);
		}
		if(iSet2.size()){
			iSet2.insert(num);
		}
		cost += num;
	}
	printf("%d\n",cost);
}
*/

//上面的花费时间较多,下面尝试用堆还维护最大最小信息
//19MS  2015-4-28 最优解
#include<iostream>
#include<algorithm>
using namespace std;

void minHeapAdjust(int *a, int i, int n){
	int child = (i<<1)|1;
	while(child<n){
		if(child+1<n && a[child]>a[child+1]){
			child++;
		}
		if(a[i]>a[child]){
			swap(a[i],a[child]);
		}else{
			break;
		}
		i = child;
		child = (i<<1)|1;
	}
}

int main(){
//	freopen("test.txt","r",stdin);
	int n,k,i,*a,cost,c;
	scanf("%d%d",&n,&k);
	a = (int *)malloc((n+k)*sizeof(int));
	for(i=0;i<n;i++){
		scanf("%d",a+i);
	}
	sort(a,a+n);
	cost = 0;
	c = a[n-1];
	for(i=n-2;i>=0;i--){
		c += a[i];
		cost += c;
	}
	printf("%d ",cost);

	while(n%(k-1)!=1){
		a[n++]=0;
	}
	for(i=(n-1)>>1;i>=0;i--){
		minHeapAdjust(a,i,n);
	}
	cost = 0;
	while(n>1){
		c = 0;
		for(i=0;i<k-1;i++){
			c += a[0];
			a[0] = a[--n];
			minHeapAdjust(a,0,n);
		}
		c += a[0];
		a[0] = c;
		minHeapAdjust(a,0,n);
		cost += c;
	}
	printf("%d\n",cost);
}





你可能感兴趣的:(ACM,南邮OJ,多元Huffman编码)