【动态规划】(二)最大子段和

最大子段和

一、什么是最大子段和

在这里,要区别一下“子段”与“子序列”。子段是指连续的一部分,例如“23”是“12345”的子段,但“24”不是。

二、如何计算最大子段和

1.暴力搜索

枚举起点 i i i与终点 j j j,计算总和并保存结果。时间复杂度为 O ( n 2 ) O(n^2) O(n2)

2.动态规划(重点)

建造一个 d p dp dp数组,其中, d p [ i ] dp[i] dp[i]表示结尾是 i i i的最大子段和
那么,我们以 − 2 , 11 , − 4 , 13 , − 5 , − 2 -2,11,-4,13,-5,-2 2,11,4,13,5,2为例,进行计算。

a[i]dp[i]
-2
11
-4
13
-5
-2

第一步,计算 d p [ 0 ] dp[0] dp[0] d p [ i ] dp[i] dp[i]有两种选择。第一种,是不选 a [ i ] a[i] a[i],那么 d p [ i ] = 0 dp[i]=0 dp[i]=0。第二种,是选 a [ i ] a[i] a[i],那么 d p [ i ] = a [ i ] dp[i]=a[i] dp[i]=a[i]。那么 d p [ 0 ] = m a x ( 0 , a [ 0 ] ) dp[0] = max(0,a[0]) dp[0]=max(0,a[0])

a[i]dp[i]
-20
11
-4
13
-5
-2

第二步,计算 d p [ 1 ] dp[1] dp[1]。跟上面一样,只不过不选的时候, d p [ i ] = a [ i ] + d p [ i − 1 ] dp[i] = a[i] + dp[i - 1] dp[i]=a[i]+dp[i1]。那么 d p [ i ] = m a x ( 0 , a [ i − 1 ] ) dp[i] = max(0,a[i - 1]) dp[i]=max(0,a[i1])

a[i]dp[i]
-20
1111
-4
13
-5
-2

接着,以此类推。

a[i]dp[i]
-20
1111
-47
1320
-515
-213

由于我们求的是最大子段和,所以还要求 d p dp dp数组里的最大值。所以,最大子段和是一个1D/1D的模型。
但是还有一点要注意的是:全部都是负数的情况。例如:-2、-3、-20、-19、-5、-13。那么最大子段和就应该是所有数中的最大值。我们可以在输入的时候完成这个操作。
根据刚才的推断,我们得知了以下几个递推公式:
d p [ 0 ] = m a x ( 0 , a [ 0 ] ) dp[0] = max(0,a[0]) dp[0]=max(0,a[0])
d p [ i ] = m a x ( 0 , a [ i − 1 ] ) dp[i] = max(0,a[i - 1]) dp[i]=max(0,a[i1])
那就上代码!

#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 1e9;
int a[101], dp[101];
int main() {
    int n;
    cin >> n;
    int ans = -inf;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        ans = max(ans, a[i]);
    }
    dp[0] = max(0, a[0]);
    for(int i = 1; i <= n; i++){
        dp[i] = max(0, a[i - 1]);
        ans = max(ans, dp[i]);
    }
    cout << ans << endl;
    return 0;
}

这次就到这里了!记得点赞关注哦!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值