K - 循环数组最大子段和

N个整数组成的循环序列a11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an1n−1,ann,a11,a22这样的序列)。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input第1行:整数序列的长度N(2 <= N <= 50000) 
第2 - N+1行:N个整数 (-10^9 <= Sii <= 10^9)
Output输出循环数组的最大子段和。 Sample Input
6
-2
11
-4
13
-5
-2
Sample Output

20


**************************************************************************

思路,其实我就是觉得很烦。很烦。

**************************************************************************

你可以把这个一串数字,分为以下几类: 

(1)第一种,从开始最后都是递增的,也就是全加起来,就是最大值。

例:5 1 2 3 4 5

(2)第二种,中间的一部分大,两头加了,就变小了。循环也是中间的。

例:6 -1 0 5 -1 5 -1

(3)第三种,两头的大,中间一部分数值,阻隔了。循环去考虑。

例:5 5 -1 -2 5 -1

(4)第四种,就前面,或者后面的小,其余的是最大值的组成部分。

例:5 1 2 -1 0 -3 或者 5 -1 0 -3 1 2

**************************************************************************

现在我们来解决他们这些情况,就可以解决了。

(1)(4)我们用一个数值,求不循环的最大值,就可以解决掉。OK。

(2)(3)如果我们把所有的数取反,之后求最大值,得到的是不是小的部分加起来的最大值,之后再把原来的数据,加起来。他们求和,不就是最大值吗?假设原来全部数据和为ans1 ,取反求最大值为ans2,那么ans = ans1 + ans2吗?或者这样来理解,我们把原来的数据求最小值,我们用所有的数据和,减去他,ans = ans1 - (-ans2),公式不就是这个吗?只不过前者我取反求的ans2而已。

**************************************************************************

(1)(2)(3)(4)合并,二者之间不就是,去取最大值吗?

**************************************************************************

这种解释,应该能懂吧?或者还有什么情况没有考虑吗?欢迎下面留言,我将一一改正。

**************************************************************************

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;

long long int a[50005];

int n;

long long int  cmp()
{
    long long int max1 = 0;
    long long int num = 0;
    for(int i=0;i<n;i++)
    {
       if(max1<0) {
            max1=a[i];
       }
       else {
          num = max(num,max1);
          max1+=a[i];
       }
    }
    return num;
}

void print_gaibian()
{
    for(int i=0; i<n; i++)
    {
        a[i] = -a[i];
    }
}
int main()
{
    scanf("%d",&n);
    long long int ans=0,ans1=0,ans2=0;
    for(int i=0;i<n;i++)
    {
        scanf("%lld",&a[i]);
        ans+=a[i];
    }
    ans1 = cmp();
    print_gaibian();
    ans2 = cmp();
    ans = max(ans1,ans+ans2);
    printf("%lld\n",ans);
    return 0;
}

posted @ 2017-07-29 16:48  让你一生残梦  阅读(300)  评论(0编辑  收藏  举报