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

1 动态规划

1.1 基本思想

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

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

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

1.2 适用条件

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

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

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

无后效性:

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

子问题的重叠性:

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

2 最长子段和问题描述

给定n个整数(可能为负数)组成的序列a1,a2,…,an。求该序列形如下式的子段和的最大值:

equation?tex=max+%5Csum_%7Bk%3Di%7D%5E%7Bj%7Da_k+%5C%5C

当所有整数均为负整数时定义其最大子段和为0。 依次定义,所求的最优值为:

equation?tex=max%5C%7B0%2C%7Bmax%7D_%7B1%5Cleq+i%5Cleq+j%5Cleq+n%7D%5Csum_%7Bk%3Di%7D%5E%7Bj%7Da_k+%5C%7D+%5C%5C

例如: (a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2) 该序列的最大子段和为:

equation?tex=%5Csum_%7Bk%3D2%7D%5E4a_k%3D20+%5C%5C

3 算法分析

通过对分治算法的分析可知,若记:

equation?tex=b%5Bj%5D+%3D+%7Bmax%7D_%7B1%5Cleq+i%5Cleq+j%7D%5C%7B%5Csum_%7Bk%3Di%7D%5Ej%7Ba%5Bk%5D%7D%5C%7D%2C1%5Cleq+j+%5Cleq+n+%5C%5C

则所求的最大子段和为:

equation?tex=max_%7B1%5Cleq+j%5Cleq+n%7D%7Bb%5Bj%5D%7D+%5C%5C

由b[j]的定义可知: 当

equation?tex=b%5Bj-1%5D%3E0时:

equation?tex=b%5Bj%5D%3Db%5Bj-1%5D%2Ba%5Bj%5D+%5C%5C

否则:

equation?tex=b%5Bj%5D%3Da%5Bj%5D+%5C%5C

由此可得b[j]的动态规划递归式:

equation?tex=b%5Bj%5D%3Dmax%5C%7B+b%5Bj-1%5D%2Ba%5Bj%5D%2C+a%5Bj%5D+%5C%7D+%EF%BC%881%E2%89%A4j%E2%89%A4n%EF%BC%89+%5C%5C

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;
}

fcb45f1c602997375ec27f053985ff71.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值