算法第四章上机实验报告

题目:最优合并问题

1.问题描述

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

输入格式:

第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。

输出格式:

输出最多比较次数和最少比较次数。

 

2.算法描述

本题运用的是贪心算法。由于长度分别为m和n的两个序列需要进行m+n-1 次比较,因此最优合并排序总比较次数一定是按序列长度从小到大并依次比较而得,最差合并排序总比较次数则相反,按照序列长度从大到小并依次比较而得。长度最小的两个序列比较相加后长度为m+n,接着再与剩余最小长度的序列比较,以此类推。因此只需要设置两个长度分别为序列个数的数组,一个按照从小到大排,另一个从大到小排,第一个和第二个元素相加后再返回所在数组重新排序,与下一个最小的元素继续累加。本问题有点类似哈夫曼编码问题,当求最优合并排序时,长度越小的序列所代表的点离二叉树的根结点越远。求最差合并排序时则相反。

时间复杂度:

最少比较次数:O(nlogn)

最多比较次数:O(n)

空间复杂度:O(n)

 

3.编程代码

#include <bits/stdc++.h>
using namespace std;
bool cmp(int a, int b){
return a>b;
}
int main(){
int k;
int a[1000], b[1000];
int Min = 0, Max = 0;
cin>>k;
for(int i=0; i<k; i++)
{
cin>>a[i];
b[i]= a[i];
}
sort(a, a+k);
sort(b, b+k, cmp);
for(int i=0; i<k-1; i++)
{
a[i+1] = a[i]+a[i+1];
Min += a[i+1]-1;
sort(a+i+1, a+k);

b[i+1] = b[i]+b[i+1];
Max += b[i+1]-1;
sort(b+i+1, b+k ,cmp);
}
cout<<Max<<' '<<Min<<endl;
return 0;
}

 

4.对贪心算法的理解

贪心算法与动态规划算法有点类似,但又有所区别。贪心算法是选择当前一步的最优选择,即局部最优解,在一些选择问题上往往比动态规划法更加直接明了且更为简洁,但把所有步骤完成之后,往往也能得到整体的最优解。总之,贪心算法也是一种追求效益最大化的解决问题方法,但也离不开最优子结构的基本性质,都是从小问题上找最优解进而得到问题最优解的过程。

 

 

posted @ 2021-11-11 15:57  zbjzbj  阅读(50)  评论(0编辑  收藏  举报