POJ 2479的简单想法

来源:互联网 发布:mysql front最新 编辑:程序博客网 时间:2024/04/30 00:16

这道题是简单的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\n",max);
    }
    return 0;
}

0 0
原创粉丝点击