题目链接:http://soj.sysu.edu.cn/1091
思路:这是一道关于求和最大的相连子序列的题。用dp[i]表示以a[i]为结尾的和最大的相连子序列,此问题的状态转移方程为:dp[i]=max(a[i],dp[i-1]+a[i]),结果为max(dp[1],dp[2]…,dp[n])。本题相当于把数组分成两段,求(这两段的(和最大的相连子序列)的和)的最大值。由于求数组和最大的相连子序列的复杂度为o(n),容易由此想到o(n^2)的做法。当然更优的做法用max_begin[i]表示前i个数和最大的相连子序列的值,用max_end[n-1-i]表示后i个数和最大的相连子序列的值,用类似头尾指针的方法从头到尾,再从尾到头遍历一遍即可求出max_begin[i]和max_end[n-1-i]。然后再遍历一遍求max(max_begin[i]+max_end[i+1]),该算法复杂度为o(2n+n),其实也即o(n)。
代码一:复杂度o(n^2),超时!
#include <iostream>
#include <cstdio>
#define MAX -20001
using namespace std;
int maxsum(int a[],int m,int n){
int max=MAX;
int sum=0;
for(int i=m;i<=n;i++){
sum+=a[i];
if(sum>max)
max=sum;
if(sum<0)
sum=0;
}
return max;
}
int main(){
int T;
cin>>T;
while(T>0){
T--;
int n;
int max=MAX;
cin>>n;
int a[n+1];
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<(n-1);i++){
if(max<(maxsum(a,1,i)+maxsum(a,i+1,n-1)))
max=maxsum(a,1,i)+maxsum(a,i+1,n-1);
}
cout<<max<<endl;
}
return 0;
}
代码二:复杂度:o(n),通过!
#include <iostream>
#include <cstdio>
#define MAX -20001
using namespace std;
int main(){
int T;
scanf("%d",&T);
while(T>0){
T--;
int n;
scanf("%d",&n);
int a[n+1];
int max=MAX;
int max_begin[n+1],max_end[n+1];
int max1=MAX,max2=MAX;
int sum1=0,sum2=0;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++){
sum1+=a[i];
if(sum1>max1)
max1=sum1;
if(sum1<0)
sum1=0;
max_begin[i]=max1;
sum2+=a[n-1-i];
if(sum2>max2)
max2=sum2;
if(sum2<0)
sum2=0;
max_end[n-1-i]=max2;
}
for(int i=0;i<(n-1);i++){
if(max<(max_begin[i]+max_end[i+1]))
max=max_begin[i]+max_end[i+1];
}
printf("%d\n",max);
}
return 0;
}