动态规划解最大子段和问题

13 篇文章 2 订阅

在这里插入图片描述

1 动态规划

1.1 基本思想

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。

与分治法的区别在于,适用于动态规划算法求解的问题,经分解得到的子问题往往不是互相独立的;若用分治法求解,则分解得到的子问题数目太多,导致最终解决原问题需指数时间。原因在于:虽然子问题的数目常常只有多项式量级,但在用分治法求解时,有些子问题被重复计算了许多次,如果可以保存已解决的子问题的答案,就可以避免大量重复计算,从而得到多项式时间的算法。

动态规划法的基本思路是:构造一张表来记录所有已解决的子问题的答案(无论算法形式如何,其填表格式是相同的)。

1.2 适用条件

适用动态规划的问题必须满足最优化原理无后效性

最优化原理(最优子结构性质):

最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质

无后效性:

将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。

子问题的重叠性:

动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间

2 最大子段和问题描述

给定n个整数(可能为负数)组成的序列a1,a2,…,an。求该序列形如下式的子段和的最大值:
m a x ∑ k = i j a k max \sum_{k=i}^{j}a_k maxk=ijak
当所有整数均为负整数时定义其最大子段和为0。
依次定义,所求的最优值为:
m a x { 0 , m a x 1 ≤ i ≤ j ≤ n ∑ k = i j a k } max\{0,{max}_{1\leq i\leq j\leq n}\sum_{k=i}^{j}a_k \} max{0,max1ijnk=ijak}

例如: (a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2)
该序列的最大子段和为:
∑ k = 2 4 a k = 20 \sum_{k=2}^4a_k=20 k=24ak=20

3 算法分析

通过对分治算法的分析可知,若记:
b [ j ] = m a x 1 ≤ i ≤ j { ∑ k = i j a [ k ] } , 1 ≤ j ≤ n b[j] = {max}_{1\leq i\leq j}\{\sum_{k=i}^j{a[k]}\},1\leq j \leq n b[j]=max1ij{k=ija[k]},1jn
则所求的最大子段和为:
m a x 1 ≤ j ≤ n b [ j ] max_{1\leq j\leq n}{b[j]} max1jnb[j]

由b[j]的定义可知:
b [ j − 1 ] > 0 b[j-1]>0 b[j1]>0时:
b [ j ] = b [ j − 1 ] + a [ j ] b[j]=b[j-1]+a[j] b[j]=b[j1]+a[j]
否则:
b [ j ] = a [ j ] b[j]=a[j] b[j]=a[j]
由此可得b[j]的动态规划递归式:
b [ j ] = m a x { b [ j − 1 ] + a [ j ] , a [ j ] } ( 1 ≤ j ≤ n ) b[j]=max\{ b[j-1]+a[j], a[j] \} (1≤j≤n) b[j]=max{b[j1]+a[j],a[j]}1jn

4 C++实现

int maxSubArray(vector<int>& nums) {
    int size=nums.size();
    int* b = new int[size];
    b[0]=nums.at(0);
    for(int i=1;i<size;i++){
        if(b[i-1]<0){
            b[i]=nums.at(i); 
        }else{
            b[i]=b[i-1]+nums.at(i);
        }
    }
    int maxV=b[0];
    for(int i=0;i<size;i++){
        if(maxV<b[i]){
            maxV=b[i];
    	}
    }
    return maxV;
}

在这里插入图片描述

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一朝英雄拔剑起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值