Try Again

最大子段和 模板题 51Nod 1049

N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值。当所给的整数均为负数时和为0。

例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N + 1行:N个整数(-10^9 <= A[i] <= 10^9)
Output
输出最大子段和。
Input示例
6
-2
11
-4
13
-5
-2
Output示例
20
给一组数据:http://paste.ubuntu.com/25117542/
方法一:分冶法,递归求解,每次将所求区间折半,一个从中间往左便利,一个从中间向右便利(保证和值存在于连续的区间)即一个左值,一个右值,两者相加求和值,三者比较求最大,不断递归,求最大区间和
suml(1,n)=sum(1,n/2),sumr(1,n)=sum(n/2+1,n);sum=suml+sumr;sum=max(sum,max(suml,sumr));
[1]、a[1:n]的最大子段和与a[1:n/2]的最大子段和相同; 
[2]、a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;
[3]、a[1:n]的最大字段和为,且1<=i<=n/2,n/2+1<=j<=n。

    可用递归方法求得情形[1],[2]。对于情形[3],可以看出a[n/2]与a[n/2+1]在最优子序列中。因此可以在a[1:n/2]中计算出,并在a[n/2+1:n]中计算出。则s1+s2即为出现情形[3]时的最优值。

代码如下:

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
#define lowbit(x) (x&(-x))
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define MAX 100000000000000000
#define MOD 1000000007
#define PI 3.141592653589793238462
#define INF 0x3f3f3f3f3f
#define mem(a) (memset(a,0,sizeof(a)))
typedef long long ll;
ll a[50006],n;
ll TDQ(ll *a,ll left,ll right)
{
    if(right==left)
    {
        return a[left]>0?a[left]:0;
    }
    ll mid=(left+right)>>1;
    ll leftsum=TDQ(a,left,mid);
    ll rightsum=TDQ(a,mid+1,right);
    ll suml=a[mid],sumr=a[mid+1],sl=0,sr=0;
    ll sum;
    for(ll i=mid;i>=left;i--)
    {
        sl+=a[i];
        suml=max(suml,sl);
    }
    for(ll i=mid+1;i<=right;i++)
    {
        sr+=a[i];
        sumr=max(sumr,sr);
    }
    sum=suml+sumr;
    sum=max(sum,max(leftsum,rightsum));
    return sum;
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    ll sum=TDQ(a,1,n);
    printf("%lld\n",sum);
    return 0;
}

 

方法二:动态规划

区间和b大于0时就往下加,否则归零。

//最大字段求和动态规划
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
#define lowbit(x) (x&(-x))
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define MAX 100000000000000000
#define MOD 1000000007
#define PI 3.141592653589793238462
#define INF 0x3f3f3f3f3f
#define mem(a) (memset(a,0,sizeof(a)))
typedef long long ll;
ll dp[50006],a[50006],n;
int main()
{
    int ans=0;
    scanf("%I64d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%I64d",&a[i]);
        if(a[i]<0) ans++;
    }
    ll sum=0,sumson=0;
    for(int i=1;i<=n;i++)
    {
        if(sumson>0) sumson+=a[i];
        else sumson=a[i];
        sum=max(sum,sumson);
    }
    printf("%I64d\n",sum);
    return 0;
}

 

posted @ 2017-07-18 16:56  十年换你一句好久不见  阅读(202)  评论(0编辑  收藏  举报