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; }