循环数组的最大子段和

问题描述:

N个整数组成循环序列,求这个序列的最大子段和。

例如:-2   11  -4  13  -5  -2    ANSWER: 20

解决:

解决这个问题需要有求解最大子段和的基础。

循环数组的最大子段和有两种情况: 一种是普通情况,另一种就是跨越一部分头和尾的情况。

对于第二种情况,如果拥有最大和的子段跨越了头和尾,那这时,中间的那一段就是一个 “最小子段和” ,因为序列的总和是一定的。

那么,怎么知道这个最小子段在哪里呢,我们只要把所有的数都取负,再求一次最大子段和就可以了。

那么也就是说,循环数组的最大子段和,就是求了两次最大子段和。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
ll a[50005],b[50005];
ll mxsub(ll a[],int n)
{
    ll sum=-999999999,b=0;
    for(int i=0;i<n;i++)
    {
        if(b>0) b+=a[i];
        else b=a[i];
        if(b>sum) sum=b;
    }
    return sum;
}
int main()
{
    int n; 
    while(scanf("%d",&n)!=EOF)
    {
        ll s=0;
        for(int i=0;i<n;i++)
        {
            scanf("%lld",&a[i]); //输入序列
            s+=a[i];  // 求整个序列的和
            b[i] = -a[i]; // 把整个序列取负放在另一个序列里
        }
        ll ans=mxsub(a,n); //  普通情况下的最大子段和
        ll ans2=s + mxsub(b,n);  // 跨越头和尾的

        ans = max(ans,ans2);  // 两者取大
        printf("%lld
",ans);
    }
    return 0;
} 

如果有什么不对的地方,还请各位大神批评指正~

原文地址:https://www.cnblogs.com/ember/p/4716489.html