动态规划 最大子段和

Posted --zz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划 最大子段和相关的知识,希望对你有一定的参考价值。

子段与子段和的概念:

  给定一个由数字组成的序列,其中一段连续的序列称为一个子段(假设非空),子段中所有的数字和就是为 子段和


例子:

   {1,2,3,4} ,

   子段有 {1} {1,2} {1,2,3} {1,2,3,4} {2,3} {2,3,4} {3,4} {4}

 

O(n2) 枚举的做法:

    for(int i=0;i<n;++i){
        long sum = 0;
        for(int j=i;j<n;++j){
            sum += a[j];
            if(sum > nMax){
                nMax = sum;
            }
        }
    }

 

通过观察发现。

(1) 整个序列都是负数,那么 最大子段和 为 最小的负数 。

(2) 如果都是正数,那么 最大子段和 就是 整个序列的的和。

(3) 如果有正有负,那么 最大的子段和 >= 整个序列的最大值,

          那么我们可以假设一个变量sum = 0; 来记录当前的子段和。

          ans 记为 整个序列的最大值

          因为要得到最大的子段 假设{ n1,n2,n3 },那么这个子段前缀 {n1,n2} 一定不会 < 0

          要得到 更大的子段和,我们就不会用 < 0 的子段和 来 拖累 后面的子段和。

          用 ans = max(ans , sum)。来求出结果

 

O(n) 动态规划实现代码:

#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 0x7fffffff;
int num[101];
int main() {
    int N;
    cin >> N;
    for(int i=0;i<N;i++){
        cin >> num[i];
    }
    int ans = -inf;
    for(int i=0;i<N;i++){
        ans = max(ans,num[i]);
    }
    if(ans <= 0){
        cout << ans << endl;
    }else{
        int sum =0;
        for(int i=0;i<N;i++){
            if(sum + num[i] < 0){
                sum = 0;
            }else{
                sum += num[i];
            }
            ans = max(ans,sum);
        }
        cout << ans << endl;
    }
    return 0;
}

 

以上是关于动态规划 最大子段和的主要内容,如果未能解决你的问题,请参考以下文章

动态规划入门 TYVJ1305 最大子段和(环状)

最大子段和——动态规划是如何运作的

最大m子段和问题(动态规划(又来填表了....))

动态规划入门 P1115 最大子段和(链状)

动态规划2最大子段和,编辑距离,括号匹配问题...

循环数组最大子段和(动态规划思想的巧妙转换)