多元Huffman编码问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
在一个操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次至少选2 堆最多选k堆石子合并成新的一堆,合并的费用为新的一堆的石子数。试设计一个算法,计算出将n堆石子合并成一堆的最大总费用和最小总费用。
对于给定n堆石子,计算合并成一堆的最大总费用和最小总费用。
Input
输入数据的第1 行有2 个正整数n和k(n≤100000,k≤10000),表示有n堆石子,每次至少选2 堆最多选k堆石子合并。第2 行有n个数(每个数均不超过 100),分别表示每堆石子的个数。
Output
将计算出的最大总费用和最小总费用输出,两个整数之间用空格分开。
Sample Input
7 3 45 13 12 16 9 5 22
Sample Output
593 199
Hint
请注意数据范围是否可能爆 int。
Source
优化之后的:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 long long maxNum,minNum; 5 template<class T> 6 long long result(T q,int k,int flag){ 7 if(flag==1&&n>k){// 求最小的 更新 8 int tmp=n; 9 while(tmp>k) tmp=tmp-(k-1); 10 for(int i=0;i<k-tmp;i++) q.push(0); 11 } 12 long long rst=0; 13 while((int)q.size()>k){ 14 long long sum=0;//sum k个 先后堆顶相加的值,合并之后,需要把sum 继续放进 优先队列里面 ,继续参与下面的合并 15 for(int i=0;i<k;i++){ 16 sum+=q.top();//sum 加上堆顶的值 17 q.pop();//同时需要把这个 堆顶的值删除 18 } 19 rst+=sum;//合并 费用 更新 20 q.push(sum);//将合并的值 继续放进 优先队列 参与 下面的合并 21 } 22 while(!q.empty()){//合并 之后 优先队列(即堆) 里面还剩下 k 个 数据 这两堆合并 的费用 就是它们的两个的和 23 rst+=q.top();//费用值 + 剩余的 两对 合并费用 结束 24 q.pop(); 25 } 26 return rst;//返回 27 } 28 int main() 29 { 30 int k,data; 31 priority_queue<long long> q;//默认 从大 到小 32 priority_queue<long long,vector<long long>,greater<long long> > p; //从小到大的顺序排列队列中的数据 cin>>n>>k;//输入n堆石子,每次至少选2 堆最多选k堆石子合并 33 cin>>n>>k; 34 for(int i=0;i<n;i++){ 35 cin>>data; 36 q.push(data); 37 p.push(data); 38 } 39 maxNum=result(q,2,0);//k =2 求最大 k=2 40 minNum=result(p,k,1);// k堆 41 cout<<maxNum<<" "<<minNum<<endl; 42 return 0; 43 }