题目链接http://poj.org/problem?id=2479
题目大意:给定数组a求数组a中两个大子序列之和的最大值
思路:对a数组进行扫描求出以左端点开始到右端点的最大子序列之和
再次扫描求出以右端点到左端点的最大子序列之和,
例如 :
a:1 -1 2 2 3 -3 4 -4 5 -5
sum1:1 0 2 4 7 4 8 4 9 4
sum2:9 8 9 7 5 2 5 1 5 -5
(sum1为从左到右扫描的子序列之和,sum2为从右到左的子序列之和,sum2的储存也是按照从右到左)
从左到右扫描sum1第i位储存从0到i的最大值(也就是a从0~i的最大子序列之和)
从右到左扫描sum2第i位储存从i到n-1的最大值(也就是a从i~n-1的最大子序列之和)
sum1:1 1 2 4 7 7 8 8 9 9
sum2:9 9 9 7 5 5 5 5 5 -5
这时题目就比较明了了,sum1[i]+sum2[i+1]就是以第i位为分段的两个最大子序列之和
扫描一遍就能求出最大值了
poj2479的代码,poj2593同理
//Creat Time: 2013年08月02日 星期五 16时12分03秒 //File Name: poj2479.cpp //--Author--: GreedyDaam #include<stdio.h> #include<stdlib.h> #include<string.h> #include<algorithm> #pragma comment(linker,"/STACK:102400000,102400000")//设置栈大小 using namespace std; #define MAX 50005 int a[MAX],sum1[MAX],sum2[MAX]; int dp(int n){ int i; sum1[0]=a[0]; for(i=1;i<n;i++){ if(a[i]>0){ if(sum1[i-1]<0)sum1[i]=a[i]; else sum1[i]=sum1[i-1]+a[i]; }else{ if(a[i]+sum1[i-1]<=0)sum1[i]=a[i]; else sum1[i]=sum1[i-1]+a[i]; } } sum2[n-1]=a[n-1]; for(i=n-2;i>=0;i--){ if(a[i]>0){ if(sum2[i+1]<0)sum2[i]=a[i]; else sum2[i]=sum2[i+1]+a[i]; }else{ if(a[i]+sum2[i+1]<=0)sum2[i]=a[i]; else sum2[i]=sum2[i+1]+a[i]; } } for(i=1;i<n;i++){ if(sum1[i]<sum1[i-1])sum1[i]=sum1[i-1]; } for(i=n-2;i>=0;i--){ if(sum2[i]<sum2[i+1])sum2[i]=sum2[i+1]; } for(i=1;i<n;i++){ sum1[i-1]+=sum2[i]; } int sum=0x80000000; for(i=0;i<n-1;i++){ if(sum1[i]>sum)sum=sum1[i]; } return sum; } int main(){ //freopen("input.txt","r",stdin); int t,n,i; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=0;i<n;i++){ scanf("%d",&a[i]); sum1[i]=0; sum2[i]=0; } printf("%d\n",dp(n)); } return 0; }