poj 2479 最大连续子段和 dp算法

简介:

一、文章来由

晚上一水~~poj2479,一道简单的dp问题,回顾一下动态规划

二、求最大子段和

这道题是求一个序列中的两个子段的最大和,是求纯的最大和的一个变体,例如题目中给出的例子
1 -1 2 2 3 -3 4 -4 5 -5
In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer.
答案是 13

如何求一个序列的子段和:

int MaxSub (int a[],int N)//此为只需要求最大的和,时间复杂度是O(n)  
{  
    int *dp = new int(N);
    int max, i;

    max = dp[0] = a[0];
    for (i=1; i<N; i++)
    {
        if (dp[i-1] > 0)
            dp[i] = dp[i-1] + a[i];
        else
            dp[i] = a[i];

        if (dp[i] > max)
            max = dp[i];
    }
    delete dp;
    return max;
}

分析:

思路很清晰的写法,每次都判断,当前dp值(即子串当前最大值),如例子中的:
1 -1 2 2 3 -3 4 -4 5 -5
1 0 2 4 7 4 8 4 9 4

这样就很清楚了~~

三、解题报告

先上AC代码:

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

#define MAXN 50002
int map[MAXN];
int Ldp[MAXN];
int Rdp[MAXN];

void MaxLSub (int a[],int N)//此为只需要求最大的和,时间复杂度是O(n)  
{
    int i;

    Ldp[0] = a[0];
    for (i=1; i<N; i++)
    {
        if (Ldp[i-1] > 0)
            Ldp[i] = Ldp[i-1] + a[i];
        else
            Ldp[i] = a[i];
    }

    for(i=1; i<N; i++)
        Ldp[i] = Ldp[i]<Ldp[i-1]?Ldp[i-1]:Ldp[i];
}

void MaxRSub (int a[],int N)//此为只需要求最大的和,时间复杂度是O(n)  
{
    int i;

    Rdp[N-1] = a[N-1];
    for (i=N-2; i>-1; i--)
    {
        if(Rdp[i+1]>0)
            Rdp[i] = Rdp[i+1]+a[i];
        else
            Rdp[i] = a[i];
    }

    for (i=N-2; i>-1; i--)
        Rdp[i] = Rdp[i]<Rdp[i+1]?Rdp[i+1]:Rdp[i];
}

int main()
{
    int T,n;
    cin>>T;

    while (T--)
    {
        scanf("%d",&n);
        //cin>>n;
        for (int i=0;i<n;++i)
        {
            scanf("%d",&map[i]);
            //cin>>map[i];
        }

        MaxLSub(map,n); //生成dp
        MaxRSub(map,n);

        int res=INT_MIN;
        for (int i=1;i<=n-1;++i)
        {
            int tmp = Ldp[i-1]+Rdp[i];
            res = tmp>res?tmp:res;
        }

        cout<<res<<endl;
    }

    return 0;
}

但是这题用暴力的 MaxSub(map,i)+MaxSub(map+i,n-i) 去做,是没有用的,会TLE,后来我将cin换成scanf,也是不行的,再后来用了这个方法:


int findMax(int lb,int rb)
{
    int max=INT_MIN;
    for (int i=lb;i<=rb;++i)
    {
        max = dp[i]>max?dp[i]:max;
    }

    return max;
}

int main()
{
/////... ...
        for (int i=1;i<=n-1;++i)
        {
            //int tmp = MaxSub(map,i)+MaxSub(map+i,n-i); //n^2

            int tmp = findMax(0,i) + findMax(i+1,n)-dp[i-1];
            res = tmp>res?tmp:res;
        }
/////... ...
}

究其原因是,用 MaxSub(map,i)+MaxSub(map+i,n-i) 纯暴力方法,是 O(n^2) 的复杂度,后来改成 findMax(0,i) + findMax(i+1,n)-dp[i-1] 其实依然是 O(n^2) 的复杂度。。

AC代码是用从左往右,找出常规的最大子串,然后用

for(i=1; i<N; i++)
        Ldp[i] = Ldp[i]<Ldp[i-1]?Ldp[i-1]:Ldp[i];

求出从左往右,当前点的最大值,如果用例子中的值就是:
1 -1 2 2 3 -3 4 -4 5 -5
1 0 2 4 7 4 8 4 9 4
1 1 2 4 7 7 8 8 9 9

保证从左往右,一定是变大,找到一个点就可以找到这个点左边的最大值~~
同理,可以计算从右往左的,一个点右边的最大值,这样就用空间换时间了,但是即使这样,也只跑出了438MS。。。

而且将scanf换成cout,又TLE了

—END—


相关文章
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
1549 1
|
算法 C++
【算法】DP背包问题(C/C++)
【算法】DP背包问题(C/C++)
|
人工智能 算法 BI
【算法】 线性DP(C/C++)
【算法】 线性DP(C/C++)
【算法优选】 动态规划之简单多状态dp问题——贰
【算法优选】 动态规划之简单多状态dp问题——贰
|
算法 JavaScript 程序员
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
236 0
【算法优选】 动态规划之两个数组dp——壹
【算法优选】 动态规划之两个数组dp——壹
|
算法 JavaScript
算法(分治、贪心、dp、回溯、分支限界)总结
算法(分治、贪心、dp、回溯、分支限界)总结
305 0
|
人工智能 算法
一些算法的复习(最短路径、最小生成树、dp)
一些算法的复习(最短路径、最小生成树、dp)
157 0
|
6月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
595 0
|
6月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
383 2

热门文章

最新文章

下一篇
开通oss服务