最大字段和

211 阅读2分钟

今天写一道非常经典的题目,对于这道题做法很多,可以用枚举,分治,动态规划,枚举算法求解这类题目一般很难通过,这里我主要讲解后两种算法思想。

题目链接

题目描述

给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 n。

第二行有 n 个整数,第 i 个整数表示序列的第 i个数字 aia_i

输出格式

输出一行一个整数表示答案。

输入输出样例

输入 #1

7
2 -4 3 -1 2 -4 3

输出 #1

4

说明/提示

样例 1 解释

选取 [3,5] 子段 {3,−1,2},其和为 4。

数据规模与约定

  • 对于 40% 的数据,保证n2×103n≤2×10^3
  • 对于 100% 的数据,保证 1n2×105,104ai1041≤n≤2×10^5,−10^4≤a_i​≤10^4

解题思路(分治)

分治的思路很简单,就是将整个问题划分成若干个子问题来求解,当子问题规模较小时可以直接求解,并利用递归算法来求解,最后将子问题的解合并成原问题的解。这里,我们将原问题进行均分对于一个问题,我们将其分成左右两个子段,分别求其最大字段和,最后再比较这两个结果的大小,取最大值即可。

AC代码(分治)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long

typedef long long ll;
const int N = 200005;
int a[N];

int maxSumDC(int a[], int low, int high)
{
    if (low == high) return a[low];
    int mid = (low + high) / 2;
    int maxLeft = maxSumDC(a, low, mid);
    int maxRight = maxSumDC(a, mid + 1, high);
    int s1 = 0, max1 = -1e5, s2 = 0, max2 = -1e5;
    for (int i = mid; i >= low; i--) { s1 += a[i];  if (s1 > max1) max1 = s1; }
    for (int i = mid + 1; i <= high; i++) { s2 += a[i]; if (s2 > max2) max2 = s2; }
    int maxSum = max1 + max2;
    if (maxLeft > maxSum) maxSum = maxLeft;
    if (maxRight > maxSum) maxSum = maxRight;
    return maxSum;
}
signed main()
{
    int n;
    cin >> n;
    memset(a, 0, sizeof a);
    for (int i = 1; i <= n; i++)   cin >> a[i];
    cout<<maxSumDC(a, 1, n);
    return 0;
}

解题思路(动态规划)

动态规划的思路也很简单,我们用a数组记录每个数,b数组记录以a[i]结尾的序列的最大字段和。
状态转移:

if (b[i - 1] > 0) b[i] = b[i - 1] + a[i];
else b[i] = a[i];

如果a[i-1]结尾的最大字段和小于或等于0,那么以a[i]结尾的最大字段和就是a[i]即可,否则,就是以a[i-1]结尾的最大字段和加上a[i],同时,我们记录并更新最大值,最后输出即可。

AC代码(动态规划)

signed main()
{
    int a[200005],b[200005];
    int n;
    cin >> n;
    memset(a, 0, sizeof a);
    memset(b, 0, sizeof b);
    for (int i = 1; i <= n; i++)   cin >> a[i];
    int res = -1e5;
    for (int i = 1; i <= n; i++)
    {
        if (b[i - 1] > 0) b[i] = b[i - 1] + a[i];
        else b[i] = a[i];
        if (b[i] > res) res = b[i];
    }
    cout << res;
    return 0;
}