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;
}
AI 代码解读

分析:

思路很清晰的写法,每次都判断,当前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;
}
AI 代码解读

但是这题用暴力的 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;
        }
/////... ...
}
AI 代码解读

究其原因是,用 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];
AI 代码解读

求出从左往右,当前点的最大值,如果用例子中的值就是:
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—


目录
打赏
0
0
0
0
17
分享
相关文章
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
340 0
【算法】DP背包问题(C/C++)
【算法】DP背包问题(C/C++)
|
10月前
|
【算法优选】 动态规划之简单多状态dp问题——贰
【算法优选】 动态规划之简单多状态dp问题——贰
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
56 0
|
10月前
|
【算法优选】 动态规划之两个数组dp——壹
【算法优选】 动态规划之两个数组dp——壹
算法(分治、贪心、dp、回溯、分支限界)总结
算法(分治、贪心、dp、回溯、分支限界)总结
103 0
一些算法的复习(最短路径、最小生成树、dp)
一些算法的复习(最短路径、最小生成树、dp)
基于和声搜索优化算法的机器工作调度matlab仿真,输出甘特图
本程序基于和声搜索优化算法(Harmony Search, HS),实现机器工作调度的MATLAB仿真,输出甘特图展示调度结果。算法通过模拟音乐家即兴演奏寻找最佳和声的过程,优化任务在不同机器上的执行顺序,以最小化完成时间和最大化资源利用率为目标。程序适用于MATLAB 2022A版本,运行后无水印。核心参数包括和声记忆大小(HMS)等,适应度函数用于建模优化目标。附带完整代码与运行结果展示。
基于免疫算法的最优物流仓储点选址方案MATLAB仿真
本程序基于免疫算法实现物流仓储点选址优化,并通过MATLAB 2022A仿真展示结果。核心代码包括收敛曲线绘制、最优派送路线规划及可视化。算法模拟生物免疫系统,通过多样性生成、亲和力评价、选择、克隆、变异和抑制机制,高效搜索最优解。解决了物流仓储点选址这一复杂多目标优化问题,显著提升物流效率与服务质量。附完整无水印运行结果图示。
基于免疫算法的最优物流仓储点选址方案MATLAB仿真

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等