最优合并问题

最优合并问题

Time Limit: 1000 ms Memory Limit: 65536 KiB

Problem Description

给定k 个排好序的序列s1 , s2,……, sk , 用2 路合并算法将这k 个序列合并成一个序列。假设所采用的2 路合并算法合并2 个长度分别为m和n的序列需要m + n -1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。
为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
对于给定的k个待合并序列,计算最多比较次数和最少比较次数合并方案。
 

Input

输入数据的第一行有1 个正整数k(k≤1000),表示有k个待合并序列。接下来的1 行中,有k个正整数,表示k个待合并序列的长度。

Output

输出两个整数,中间用空格隔开,表示计算出的最多比较次数和最少比较次数。

Sample Input

4
5 12 11 2

Sample Output

78 52

Hint

 

Source

使用 优先队列  优化 ,使用模板

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 template<typename T>
 5 int result(T q){//使用模板  因为求最大 最小值 ,这两个 代码几乎一样
 6     int rst=0;
 7     while((int)q.size()>2){//两个求和
 8         int sum=0;
 9         for(int i=0;i<2;i++){
10             sum+=q.top();
11             q.pop();
12         }
13         rst+=sum;
14         q.push(sum);
15     }
16     while(!q.empty()){
17         rst+=q.top();
18         q.pop();
19     }
20     return rst;
21 }
22 int main()
23 {
24     priority_queue<int,vector<int>,less<int> > q;//从大到小  Max
25     priority_queue<int,vector<int>,greater<int> > p;// 从小 到大 Min
26     int n,data;
27     cin>>n;
28     for(int i=0;i<n;i++){
29         cin>>data;
30         q.push(data);
31         p.push(data);
32     }
33     int  maxNum=result(q);//2 路合并算法合并2 个长度分别为m和n的序列需要m + n -1次比较 
34     int  minNum=result(p);
35     cout<<maxNum-(n-1)<<" "<<minNum-(n-1)<<endl;// 所以总共 比较n-1次  最后减去 n-1即可
36     return 0;
37 }

初始:未优化

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     priority_queue<int,vector<int>,less<int> > q;//从大到小  Max
 6     priority_queue<int,vector<int>,greater<int> > p;// 从小 到大 Min
 7     int n,data;
 8     cin>>n;
 9     for(int i=0;i<n;i++){
10         cin>>data;
11         q.push(data);
12         p.push(data);
13     }
14     int  maxNum=0;//初始化 最大 费用 0
15     int  minNum=0;//初始化 最小 费用 0
16     while((int)q.size()>2){
17         int sumMax=0,sumMin=0;
18         for(int i=0;i<2;i++){
19             sumMax+=q.top();
20             q.pop();
21             sumMin+=p.top();
22             p.pop();
23         }
24         maxNum+=sumMax;
25         minNum+=sumMin;
26         q.push(sumMax);
27         p.push(sumMin);
28     }
29     while(!q.empty()){
30         maxNum+=q.top();
31         minNum+=p.top();
32         q.pop();
33         p.pop();
34     }
35     cout<<maxNum-(n-1)<<" "<<minNum-(n-1)<<endl;
36     return 0;
37 }

使用数组

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 
 6 bool cmp(int a, int b){
 7     return a>b;
 8 }
 9 
10 int main(){
11     int k;
12     int a[1010], b[1010];
13     int Min = 0, Max = 0;//此算法 ,和优先队列 差不多,每次将 算出的 最小值,最大值,在放进队列中 ,进行比较
14     cin>>k;
15     for(int i=0; i<k; i++){
16         cin>>a[i];
17         b[i]= a[i];
18     }//当取最小值保证每次的2个加数为最小便可,最大值同理取当前最大的两个值便可
19     sort(a, a+k);//最小值 排序 从小到大
20     sort(b, b+k, cmp);// 将 数据 从大到小 排序
21     for(int i=0; i<k-1; i++){
22         a[i+1] = a[i]+a[i+1];//当前 开始的 下一个 值  替换为   前两个 数之和,
23         Min += a[i+1];//最小值 更新 为 两个 最小值   最后 才算了 -(k-1)  因为 k 个数 ,要进行 k-1次比较 ,得减去 k-1 个 1  ; k-1次 (m+n-1)
24         sort(a+i+1, a+k);
25 
26         b[i+1] = b[i]+b[i+1];//此处为 最大值 ,每次加过 之和,在放进 要进行合并的序列中  在进行参与比较
27         Max += b[i+1];
28         sort(b+i+1, b+k ,cmp);
29     }
30     cout<<Max-k+1<<' '<<Min-k+1<<endl;
31     return 0;
32 }
 1 函数模板的声明形式为:
 2 template<typename(或class) T>
 3 <返回类型><函数名>(参数表)
 4 {
 5 函数体
 6 }
 7 其中,template是定义模板函数的关键字;template后面的尖括号不能省略;typename(或class)是声明数据类型参数标识符的关键字,用以说明它后面的标识符是数据类型标识符。这样,在以后定义的这个函数中,凡希望根据实参数据类型来确定数据类型的变量,都可以用数据类型参数标识符来说明,从而使这个变量可以适应不同的数据类型。例如:
 8 template<typename(或class) T>
 9 T fuc(T x, T y)
10 {
11 T x;
12 //……
13 }
原文地址:https://www.cnblogs.com/NirobertEinteson/p/11923378.html