hdu 5280 Senior's Array(最大子段和)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5280

题意:将一个长度为n的数组,将里面某一个数改为p,使改变后最大子段和最大。

题解:dp[i]=max(dp[i-1)+a[i],a[i]),表示以第 i 个数结束的最大子段和,时间复杂度为O(n)。

1)由于n<=1000,可以暴力解决,将每一个数都依次改为p,求出最大的子段和,再去这些最大子段和中最大的,时间复杂度为O(n*n);

#include <iostream>
#include <cmath>
using namespace std;

long long a[1005];
long long dp[1005];

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int  n,p,temp;
        cin>>n>>p;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        long long maxn=a[1];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                temp=a[i];
                a[i]=p;
                dp[j]=max(dp[j-1]+a[j],a[j]);
                maxn=max(maxn,dp[j]);
                a[i]=temp;
            }
        cout<<maxn<<endl;
    }
    return 0;
}

2)l[i]以 i 个数结束的最大字段和,r[i]为以第 i 个数开始的最大字段和;如果a[i]改为p在这个最大的连续字段和中,那么这段字段和为max(l[i-1],0ll)+max(r[i+1],0ll)+p;
若果a[i]-->p不连续字段和中,就只要对l[1....n-1]和r[n.....2]遍历一遍就行;

#include <iostream>
#include <cmath>
using namespace std;

long long a[1005];
long long l[1005];
long long r[1005];

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,p;
        cin>>n>>p;
        l[0]=r[n+1]=0;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            l[i]=max(a[i],a[i]+l[i-1]);
        for(int i=n;i>0;i--)
            r[i]=max(a[i],r[i+1]+a[i]);
        long long maxn=a[1];
        for(int i=1;i<=n;i++)
            maxn=max(maxn,max(l[i-1],0ll)+max(r[i+1],0ll)+p);
        for(int i=1;i<n;i++)
            maxn=max(maxn,l[i]);
        for(int i=n;i>1;i--)
            maxn=max(maxn,r[i]);
        cout<<maxn<<endl;
    }
    return 0;
}

 

posted on 2015-07-24 20:44  猫哥小俊  阅读(143)  评论(0编辑  收藏  举报

导航