最大子段和

  求数列的最大子段和

 给定了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;
}





原文地址:https://www.cnblogs.com/gaot/p/7709713.html