这道题是简单的dp例题拓展,问题是:给定一行数字,然后求这行数字中两个连续子序列和的最大值,并输出(两个子序列不能有重叠的部分);
由于是初学者,可能想法比较局限。我的总体思路是这样:这题肯定和最大求子序列有关,然后进行工作:用dp1[i]表示以第i个数结尾的最大子序列的和,用dp[i]表示已第i个数为起点的最大子序列的和;这样对于两个子序列和的最大值,把n分成2部分,[0-j],(j,n)在这两部分分别求dp1[i]得最大值和dp2[i]的最大值。这样的话,所取到的两个子序列一定不会有重合部分;
如何dp1[i],dp2[i]的最大值都[0,j],(j,n)这样的区间算的话,时间复杂度就是o(n^2),这样,我提交了试了一下,结果是tlo;然后我优化了一下:用数组max1[i]表示前i个数中dp1[j]的最大值,max2[i]表示后(i,n)中dp2[j]的最大值;
这样时间复杂度变为o(n),是不会超时的。下面是代码:
#include<cstdio>
#include<cstring>
using namespace std;
int a[60000];
int dp1[60000],dp2[60000],max1[60000],max2[60000];
int main()
{
freopen("test.txt","r",stdin);
int T;
scanf("%d",&T);
for(int i=0;i<T;i++)
{
int n;
scanf("%d",&n);
for(int j=0;j<n;j++)
{
scanf("%d",&a[j]);
}
dp1[0]=a[0];
for(int j=1;j<n;j++)
{
if(dp1[j-1]>0)
{
dp1[j]=dp1[j-1]+a[j];
}
else dp1[j]=a[j];
}
dp2[n-1]=a[n-1];
for(int j=n-2;j>=0;j--)
{
if(dp2[j+1]>0)
{
dp2[j]=dp2[j+1]+a[j];
}
else dp2[j]=a[j];
}
max1[0]=dp1[0];
for(int j=1;j<n;j++)
{
max1[j]=(max1[j-1]>dp1[j]?max1[j-1]:dp1[j]);
}
max2[n-1]=dp2[n-1];
for(int j=n-2;j>=0;j--)
{
max2[j]=(max2[j+1]>dp2[j]?max2[j+1]:dp2[j]);
}
int max=-400000;
for(int j=1;j<n;j++)
{
if(max<(max1[j-1]+max2[j]))
max=max1[j-1]+max2[j];
}
printf("%d
",max);
}
return 0;
}