POJ-2479 Maximum sum(动态规划)

最大子序列和的加强版。

借助最大子序列和,分别正向和反向遍历一遍得到left和right数组(具体含义见代码注释)

然后再对left和right数组进行修正,保存从对应元素起向左或向右的最大连续和。

最后再次遍历一遍得到最大的ans。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=50005;
int leftm[maxn];
int rightm[maxn];
int a[maxn];
int main(void){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        leftm[0]=a[0];//leftm[i]表示以i结尾的最大连续子串 
        for(int i=1;i<n;i++){
            if(leftm[i-1]>0) {
                leftm[i]=leftm[i-1]+a[i];
            }
            else{
                leftm[i]=a[i];
            }
        }
        rightm[n-1]=a[n-1];//rightm[j]表示以 j开始的最大连续子串 
        for(int j=n-2;j>=0;j--){
            if(rightm[j+1]>0) {
                rightm[j]=rightm[j+1]+a[j];
            }
            else{
                rightm[j]=a[j];
            }
        }
        
        for(int i=1;i<n;i++){//left[i]表示i左边的最大连续子串(不一定含i) 
            leftm[i]=max(leftm[i],leftm[i-1]);
        }
        for(int j=n-2;j>=0;j--){//right[j]表示j右边的最大连续子串和 
            rightm[j]=max(rightm[j+1],rightm[j]);
        }
        
        int ans=leftm[0]+rightm[1];
        for(int k=0;k+1<n;k++){
            ans=max(ans,leftm[k]+rightm[k+1]);
        //    cout<<leftm[k]<<" "<<rightm[k+1]<<endl;//test
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-04-07 21:47  KYSpring  阅读(477)  评论(0编辑  收藏  举报