zoukankan      html  css  js  c++  java
  • 最大子段和

      求数列的最大子段和

     给定了n个元素的整数列(可能为负整数),a1,a2,a3,a4....an,求形如 ai,ai+1,ai+2....aj的子段,使其和为最大。当所有的整数位负整数时,定义其最大子段为0、

     例如当(a1,a2,a3,a4,a5)=(-2,11,-4,13,-5,-2)时,其最大子段和为20.

    分治算法求解:

      分治算法中a[1:n]的最大子段和有三种情况 。a[1:n/2]和a[(n/2)+1:n]表示将数列a[1:n]等分成两段。

    数列子段和最大的三种情况:

    (1)最大子段和在a[1:n/2]中

    (2)最大子段和在a[(n)/2+1:n]中

    (3)最大子段和在a[i:j]当中,1<=i<=n/2<n/2+1<=j<=n,即最大子段的一部分在左边子段中,一部分在右边子段中

    对于(1)和(2)两种情况,可通过递归求得。对于(3),则有a[n/2]和a[n/2+1]一定在最大子段中。因此可以算出a[i:n/2]的最大值s1和aa[n/2+1:j]的最大值s2.及s1+s1为情况(3)的最优解

    代码如下

    #include <iostream>
    
    using namespace std;
    
    int MaxSum(int a[],int left,int right)
    {
        int center,left_sum,right_sum,s1,s2,lefts,rights;
        if(left==right)
        {
            if(a[left]>0)
                return a[left];
            else
                return 0;
        }
        else
        {
            center=(left+right)/2;
            left_sum=MaxSum(a,left,center);//计算情况(1)的最大值
            right_sum=MaxSum(a,center+1,right);//计算情况(2)的最大值
            s1=0;
            lefts=0;
            //从中间往两边计算
            for(int i=center;i>=left;i--)
            {
                //计算左边的最大值
                lefts+=a[i];
                if(lefts>s1)
                    s1=lefts;
            }
            s2=0;
            rights=0;
            for(int i=center+1;i<=right;i++)
            {
                //计算右边的最大值
                rights+=a[i];
                if(rights>s2)
                    s2=rights;
            }
    
            if(s1+s2<left_sum)
                return left_sum;
            else if(s1+s2<right_sum)
                return right_sum;
            else
                return s1+s2;
        }
    }
    
    int main()
    {
        int a[20],n,Max;
        printf("输入元素个数:");
        scanf("%d",&n);
        printf("输入元素:");
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        Max=MaxSum(a,1,n);
        printf("最大元素和为:%d",Max);
        return 0;
    }
    

    动态规划算法

    #include <iostream>
    
    using namespace std;
    
    #define NUM 100
    int a[NUM];
    
    int MaxSum(int n,int &besti,int &bestj)
    {
        int sum=0,b=0;
        int begin=0;
        for(int i=1;i<=n;i++)
        {
            if(b>0)
                b+=a[i];
            else
                {
                    b=a[i];
                    begin=i;
                }
            if(b>sum)
            {
                sum=b;
                besti=begin;
                bestj=i;
            }
        }
        return sum;
    }
    
    int main()
    {
        int n,sum,besti,bestj;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sum=MaxSum(n,besti,bestj);
        printf("最大子段为:");
        for(int i=besti;i<=bestj;i++)
            printf("%d ",a[i]);
        printf("
    Max=%d",sum);
        return 0;
    }
    





  • 相关阅读:
    登录验证servlet实现
    IOS开发(68)之捕获点击划屏手势
    jquery实现漂浮在网页右侧的qq在线客服插件
    深切缅怀“5.12”特大地震遇难同胞
    PHP实现微信申请退款流程实例源码
    empty和isset的区别
    ThinkPHP中实现微信支付(jsapi支付)流程
    php中正则表达式详解
    PHP与RBAC设计思路讲解与源码
    一起谈.NET技术,VS2010实践RUP4+1架构模型 狼人:
  • 原文地址:https://www.cnblogs.com/gaot/p/7709713.html
Copyright © 2011-2022 走看看