Poj 2479 Maximum sum【双向DP/最大连续和】

Maximum sum

题意:给定一个长度为N的数组,求两个连续的子序列,使得两个连续子序列的和最大。

分析:乍一看,跟最大连续和有点类似,但是,又有区别,因为对于这个题,考虑第i项两个连续子序列的最大和,不能仅仅由前i-1项递推得出,第i项两个连续子序列的最大和,与前i项和i以后的之间是存在关系的,因此这个题目是一个双向dp。

假如给定的序列为a0, a1, a2, a3, a4, ...... ,an,那么,对于任意第i项,我以第i个元素为分界点,用一个数组项pMax [i]来保存  区间 [1,i ] 的最大连续子段和【包含第i点】,然后我用nMax[i]  来保存  区间 [i,N]  的最大连续子段和,对于整个区间 [1,N] 来说,两个最大连续子序列的和 Ans = max(pMax[i] + pMaxi+1])【这时i∈[1,N]即可】,这个过程的复杂度为O(N)。这样我就将这个问题就转化为 求两个区间的最大连续和的问题了【求最大连续和的方法我便不再累赘啦】,这个过程的复杂度也为O(N),那么这样,整个问题就解决了。

附上一份ac代码【代码很糙,也没去优化了~】:

#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 50000+10;
const int INF = 0x7fffffff;
int T,N,arr[maxn];
int prev[maxn],next[maxn],ans,pMax[maxn],nMax[maxn];
//prev[i]保存以第i个元素结尾的连续和,用来求pMax
//next[i]保存以第i个元素开头的连续和,用来求nMax
int main()
{
    // freopen("input.in","r",stdin);
    for(scanf("%d",&T); T--;)
    {
        scanf("%d",&N);
        memset(prev,0,sizeof(prev));
        memset(next,0,sizeof(next));
        memset(nMax,0,sizeof(nMax));
        memset(pMax,0,sizeof(pMax));
        int pre_max,nex_max;
        for(int i = 1; i <= N; i++)
        {
            scanf("%d",&arr[i]);
            if(i == 1) pre_max = prev[i] = arr[1];
            else
            {
                if(prev[i-1] <= 0) prev[i] = arr[i];
                else prev[i] = prev[i-1]+arr[i];
            }
            pre_max = max(prev[i],pre_max);
            pMax[i] = pre_max;
        }
        nMax[N] = nex_max = next[N] = arr[N];
        for(int i = N-1; i >= 1; i--)
        {
            if(next[i+1] <= 0)
                next[i] = arr[i];
            else next[i] = next[i+1]+arr[i];
            nex_max = max(nex_max,next[i]);
            nMax[i] = nex_max;
        }
        ans = -INF;
        for(int i = 1; i < N; i++)
        {
            ans = max(pMax[i]+nMax[i+1],ans);
        }
        printf("%d\n",ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-25 19:53:33

Poj 2479 Maximum sum【双向DP/最大连续和】的相关文章

POJ 2479 Maximum sum(双向DP)

Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 36100   Accepted: 11213 Description Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below: Your task is to calculate d(A). Input The input consists o

[ACM] POJ 2479 Maximum sum (动态规划求不相交的两段子段和的最大值)

Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33363   Accepted: 10330 Description Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below: Your task is to calculate d(A). Input The input consists o

POJ 2479 Maximum sum ( DP )

题目大意: 对整数串S,求其两个不相交的子串s1.s2,使得s1+s2的值最大. 方法:DP, lt[i]代表以第i个元素结尾的串最大值 rt[i]代表以第i个元素开头的串的最大值 那么设置一个rtm[i]代表取后i个元素之中最大连续子串的和 很显然,lt[i]=max(a[i],lt[i-1]+a[i]); rt[i]=max(a[i],rt[i+1]+a[i]); rtm[i]=max(rtm[i+1],rt[i]); #include <iostream> #include <cs

POJ 2479 Maximum sum

http://poj.org/problem?id=2479 题意: 给出一个整数串,求连续子串1和连续子串2,不相交并且串1加串2的和最大. 思路: 其实就是求最大连续和,题意要求就是求两段最大连续和.我们可以从左边和右边分别求最大连续和,代码中的dp_l[i]就是1~i的最大连续和,dp_r[i]则是i~n的最大连续和. 1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<

[poj 2479] Maximum sum -- 转载

转自 CSND 想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410                                      转载请注明出处:http://blog.csdn.net/wangjian8006 题目大意: 对于连续的整数和的串s1和s2,s1与s2不相交,使得s1+s2最大 解题方法: DP.  lt[i]代表以第i个元素结尾的串最大值  rt[i]代表以第i个元素开头的串的最大

poj 2479 Maximum sum(递推)

?? 题意:给定n个数,求两段连续不重叠子段的最大和. 思路非常easy.把原串划为两段.求两段的连续最大子串和之和,这里要先预处理一下,用lmax数组表示1到i的最大连续子串和,用rmax数组表示n到i的最大连续子串和,这样将时间复杂度降为O(n). #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include&l

【UVA】108 - Maximum Sum(DP矩阵)

n^3的复杂度计算最小子矩阵,用了最大连续和的DP算法. 14273282 108 Maximum Sum Accepted C++ 0.013 2014-09-27  #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF = 1 << 30; const int maxn = 127 + 3; int mat[maxn][maxn]

poj 2479 max sum

Maximum sumTime Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u SubmitStatus Description Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below: Your task is to calculate d(A). Input The input consists

Ural 1146 Maximum Sum(DP)

题目地址:Ural 1146 这题是求最大子矩阵和.方法是将二维转化一维. 首先用n*n的方法来确定矩阵的列.需要先进行预处理,只对每行来说,转化成一维的前缀和,这样对列的确定只需要前后两个指针来确定,只需要用前缀和相减即可得到.前后两个指针用n*n的枚举. 确定好了哪几列,那么再确定行的时候就转化成了一维的最大连续子序列的和.再来一次O(n)的枚举就可以. 这样,总复杂就变成了O(n^3),对于n为100来说,已经足够了. 代码如下: #include <iostream> #include