蓝桥杯训练5 最大子段和(DP)

最大子段和 - DP

Description

N N N 个整数组成的序列 a [ 1 ] , a [ 2 ] , a [ 3 ] , … , a [ n ] a[1],a[2],a[3],…,a[n] a[1],a[2],a[3],,a[n],求该序列如 a [ i ] + a [ i + 1 ] + … + a [ j ] a[i]+a[i+1]+…+a[j] a[i]+a[i+1]++a[j] 的连续子段和的最大值。当所给的整数均为负数时和为 0 0 0

例如: − 2 , 11 , − 4 , 13 , − 5 , − 2 -2,11,-4,13,-5,-2 2,11,4,13,5,2,和最大的子段为: 11 , − 4 , 13 11,-4,13 11,4,13。和为 20 20 20

Input
1 1 1 行:整数序列的长度 N ( 2 ≤ N ≤ 50000 ) N (2≤N≤50000) N(2N50000)
2 − N + 1 2−N+1 2N+1 行: N N N 个整数 ( − 1 0 9 ≤ A [ i ] ≤ 1 0 9 ) (−10^9≤A[i]≤10^9) (109A[i]109)
Output
输出最大子段和

input
6
-2
11
-4
13
-5
-2
output
20

解题思路:
动态规划。 d p [ i ] dp[i] dp[i] 表示 以 a [ i ] a[i] a[i] 结尾的子段的最大和。
两种情况:以 a [ i ] a[i] a[i] 结尾的子段,①在以 a [ i − 1 ] a[i-1] a[i1] 结尾的子段后面加上 a [ i ] a[i] a[i], ②新的子段 a [ i ] a[i] a[i]
状态转移方程: d p [ i ] = m a x ( d p [ i − 1 ] + a [ i ] , a [ i ] ) ; dp[i] = max(dp[i - 1] + a[i], a[i]); dp[i]=max(dp[i1]+a[i],a[i]); 遍历数组 d p dp dp 找最大值。注意数据开 l o n g long long l o n g long long

Code:

#include 
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int n;
ll a[200002];
ll dp[200002];
int main() {
    ll ans = -inf;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++) {
        dp[i] = max(dp[i - 1] + a[i], a[i]);
        ans = max(ans, dp[i]);
    }
    printf("%lld\n", ans);
    return 0;
}

你可能感兴趣的:(动态规划)