算法第四章上机实践报告

1、实践题目:最优合并问题

2、问题描述:

 3、算法描述(说明你的贪心策略,并且参考会场安排问题,利用反证法证明贪心选择和最优子结构性质):

贪心策略:最多比较次数:选择最大和第二大的数,依次递减;最少比较次数:选择最小和第二小的数;

反证法证明:

  设序列集合E={1,2,...,n}以按长度大小的非减顺序排列,序列1具有最短的长度。

  1、首先必有最优解包含序列1

  不然设AE是最优解且A中最短的序列是k。若k=1,则最优解包含序列1,若k>1,则序列1必比序列k短,可以代替序列k,令B=A-{K}+{1},则B也是一个最优解。

  2、进一步,若A是原问题的包含序列1的最优解,则A'=A-{1}是活动集合E'=E-{1}的最优解

  不然设B'是E'的解且|B'|>|A'|,则B'∪{1}是E的解且|B'|+1>|A|,此与A是最优解矛盾。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int k;
    cin>>k;
    int* a = new int[k];
    int* b = new int[k];
    
    for(int i = 0; i < k; i++)
    {
        cin>>a[i];
        b[i] = a[i];
    }

    sort(a, a + k);

    int ssum = 0;
    int smark = 0;
    while(smark < k - 1)
    {
        ssum = ssum + a[smark] + a[smark+1] - 1;
        a[smark] = a[smark] + a[smark+1];
        a[smark+1] = 0;
        smark++;
        sort(a, a + k);
    }
    sort(b, b + k);
    int bsum = 0;
    //int bmark = 0;
    for(int i = 1; i <= k - 1; i++)
    {
        bsum = bsum + b[k - 1] + b[k - 2] - 1;
        b[k - 1] = b[k - 1] + b[k - 2];
        b[k - 2] = 0;
       // bmark++;
        sort(b, b + k);
    }
    cout<<bsum<<" ";
    cout<<ssum;
    return 0;
}
View Code

4、算法时间及空间复杂度分析(要有分析过程)

时间复杂度:排序:O(nlogn),合并(n-1)(2*O(1)+O(n))=O(n^2);

空间复杂度:O(n^2);

5、心得体会(对本次实践收获及疑惑进行总结):

与上一章的动态规划来说,其实有些相似,动态规划只要找出动态规划公式,其余问题不大,贪心算法也是如此,只需要弄清楚贪心策略,其余也很容易,对于此次的第二题,我们上机时是没有头绪的,我们想到了将该数%10分离出各个数字存入数组,但由于过于麻烦,所以没能做出来,经过老师的提醒,把他设成一个字符串,问题便简单许多,总的来说,是我们见识的题目还不够多,有些想当然就钻进死胡同里,这时候不如跳出陷阱,重新思考会得到更好的算法。

原文地址:https://www.cnblogs.com/yyxbokewang/p/11853678.html