算法设计--最大子段和问题--分治法

算法设计--最大子段和问题--分治法

  给定由n个整数组成的序列(a1, a2, …, an),最大子段和问题要求该序列形如 \sum_{k=i}^{j}a_{k} 的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0。例如,序列(-20, 11, -4, 13, -5, -2)的 最大子段和为:\sum_{k=2}^{4} a_{k}=20

最大子段和问题的分治策略是:

(1)划分:按照平衡子问题的原则,将序列(a1, a2, …, an)划分成长度相同的两个子序列(a1, …, a[n/2]      )和(a[n/2], …, an),则会出现以下三种情况:

① a1, …, an的最大子段和=a1, …,a[n/2] 的最大子段和;

② a1, …, an的最大子段和=a[n/2]+1, …, an的最大子段和;

③ a1, …, an的最大子段和=\sum_{k=i}^{j} a_{k},且1<=i<=[n\2],[n/2]+1<=j<=n

(2)求解子问题:对于划分阶段的情况①和②可递归求解,情况③需要分别计算s1=max\sum_{k=i}^{[n/2]]}a_{k}(1<=i<=[n/2])

(3)合并:比较在划分阶段的三种情况下的最大子段和,取三者之中的较大者为原问题的解。

#include<bits/stdc++.h>
using namespace std;
int MaxSum(int a[],int left,int right)
{
    int sum=0;
    if(left==right)
    {
        if(a[left]>0)sum=a[left];
        else sum=0;
    }
    else
    {
        int center=(left+right)/2;
        int leftsum=MaxSum(a,left,center);
        int rightsum=MaxSum(a,center+1,right);
        int s1=0;int lefts=0;
        for(int i=center;i>=left;i--)
        {
            lefts+=a[i];
            if(lefts>s1)s1=lefts;
        }
        int s2=0;int rights=0;
        for(int j=center+1;j<=right;j++)
        {
            rights+=a[j];
            if(rights>s2)s2=rights;
        }
        sum=s1+s2;
        if(sum<leftsum)sum=leftsum;
        if(sum<rightsum)sum=rightsum;
    }
    return sum;
}
int main()
{
    int a[6]={-20,11,-4,13,-5,-2};
    int b=MaxSum(a,0,5);
    cout<<b;
}

猜你喜欢

转载自blog.csdn.net/qq_43238335/article/details/105372644