多元Huffman编码问题

问题描述:在一个操场的四周摆放着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
--------------------- 
 

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

int min_k(int *a,int start,int end)  //合并k堆 
{
	int result=0;
	for(int i=start;i<end;i++)
	{
		result+=a[i];
	}
	return result;
 } 
int minresult(int *a,int n,int k)			//对最小的值贪心,及使得最大的数所加次数最少,及每次按k次合并,并从小到大合并 
{
	int t=0,min=0,result=0,i,j;
	int b[n];			//b数组内数据为新的石子堆中的石子个数 
	memset(b,0,sizeof(b));  //对b数组清零操作 
	if(n<k&&n!=1)		//当最后石子堆不够k时,直接合并 
	{
		for(int i=0;i<n;i++)
		{
			result+=a[i];
		//	cout<<"ai"<<a[i]<<" ";
		}
		cout<<endl;
		return result;
	}
	if(n==1)	//当最后的石子堆刚好为k时,直接返回 
	{
		return result;
	}
	
	sort(a,a+n,less<int>());			//升序排序 
	/*cout<<"数组详情:"<<endl;
	for(int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;*/
	t=n/k+n%k;					//t表示新的数组中的元素个数,即合并后有t个石子堆 
	for(i=0;i<n/k;i++)		//进行n/k次合并,剩余n%k个石子堆留给下次合并 
	{
		b[i]=min_k(a,i*k,i*k+k);
		result+=b[i];
		//cout<<"b为"<<b[i]<<endl;
	}
	for(j=i;j<n%k+i;j++)		//对余下的石子堆保留,留给下次合并 
	{
		b[j]=a[i*k+j-i];
		//cout<<"bj为:"<<b[j]<<endl; 
	}
	
	return result+=minresult(b,t,k);
}
int maxresult(int *a,int n,int k)  //贪心,每次只取最少的,并从大到小合并,这样使得最大的数所加的次数最多,从而得到最大数 ()*(n-1); 
{
	sort(a,a+n,greater<int>());			//降序排序 
	int max=(a[0]+a[1])*(n-1);
	for(int i=2;i<n;i++)
	{
		max+=a[i]*(n-i);
	}
	return max;
}

void solve(int n,int k)
{
	int a[n+1];
	cout<<"请输入"<<n<<"个石子堆,各堆的石子数:"; 
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}

	cout<<"最大结果为:"<<maxresult(a,n,k)<<endl;
	cout<<"最小结果为:"<<minresult(a,n,k)<<endl;
}






int main()
{
	int n,k;
	cout<<"请分别输入n和k的值:";
	cin>>n>>k;
	solve(n,k);
	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值