14.最优合并问题(贪心)
作者:互联网
题目描述:
给定k 个排好序的序列s1 , s2,……, sk , 用2 路合并算法将这k 个序列合并成一个序列。假设所采用的2 路合并算法合并2 个长度分别为m和n的序列需要m + n -1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。
为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
对于给定的k个待合并序列,计算最多比较次数和最少比较次数合并方案。
输入:
输入数据的第一行有1 个正整数k(k≤1000),表示有k个待合并序列。接下来的1 行中,有k个正整数,表示k个待合并序列的长度。
输出:
输出两个整数,中间用空格隔开,表示计算出的最多比较次数和最少比较次数。
样例①
输入
4
5 12 11 2
输出
78 52
代码:
#include<bits/stdtr1c++.h>
using namespace std;
//获得最多比较次数
int getMax(vector<int> v1) {
int sum1 = 0; //sum记录次数
sort(v1.begin(), v1.end(), greater<int>()); //按照从大到小排序
//合并的时候,当size=1时,说明只剩下1个数了,合并完毕
while (v1.size() > 1) {
int t = 0; //t为临时变量,用来记录 两个序列合并之后的长度
t += (v1[0] + v1[1]);
v1[1] = t; //让第二个先变成合并之后的长度,两个最大的相加之后赋给第二个值,可以保证还是有序的
sum1 += (t - 1);
v1.erase(v1.begin()); //把开头第一个数删掉
}
return sum1;
}
//获得最小比较次数,稍微麻烦些,需要每合并两个就要进行排序一次,因为合并完的需要重新放到vector中,但是无论是放到开头还是放到末尾,都不能保证有序,所以需要重新排序。
int getMin(vector<int> v2) {
int sum2 = 0;
sort(v2.begin(), v2.end());
while (v2.size() > 1) {
int t = 0;
t += (v2[0] + v2[1]);
v2.emplace_back(t);
sum2 += (t - 1);
v2.erase(v2.begin(), v2.begin() + 2);
sort(v2.begin(), v2.end());
}
return sum2;
}
int main() {
int n;
vector<int> v;
cin >> n;
int num;
for (int i = 0; i < n; i++) {
cin >> num;
v.emplace_back(num);
}
cout << getMax(v) << " " << getMin(v);
return 0;
}
标签:begin,14,int,合并,v1,v2,序列,最优,贪心 来源: https://www.cnblogs.com/Fare-well/p/16629450.html