poj 2479 Maximum sum(线性dp)

题目链接:http://poj.org/problem?id=2479

思路分析:假设数组为A[1, 2, …, n],则问题需要求数组A[s1, s1+1, …, t1]中的最大连续子段和与A[s2, …. , t2]中的最大连续子段和的和最大;

该问题实质上可以转换为求数组的最大子段和问题,只要预处理求出A[1, k]和A[k, n]数组的最大连续子段和,再枚举k的所有可能取值求

A[1, k]和A[k+1, n]中的最大连续子段和的和,再求出所有的情况中的最大值即可;

PS:在题目中s2不一定等于t1+1,但是要求出两个子段A[s1, .., t1]和A[s2, .., t2]中的最大连续子段和的和最大的情况,当s2 == t1+1时,

因为A[t1+1, …, t2]中的最大连续子段和必定大于等于A[s2, …, t2](s2>t1+1)中的最大连续子段和,所以A[s1, .., t1]与A[t1+1,…, t2]的最大连续子段

的和必定大于A[s1, …,t1]与A[s2, .., t2]最大连续子段的和,所以s2>t1+1的其他情况可以不必求解;

 

 

代码如下:

#include <cstdio>
#include <iostream>
using namespace std;

const int MAX_N = 50000 + 10;
int arr[MAX_N], dp_s[MAX_N], dp_r[MAX_N];
int arr_num;

int main(int argc, char *argv[])
{
    int case_num, ans;

    scanf("%d", &case_num);
    while (case_num--)
    {
        int temp_ans, sum;

        scanf("%d", &arr_num);
        for (int i = 0; i < arr_num; ++i)
            scanf("%d", &arr[i]);

        temp_ans = INT_MIN, sum = 0;
        for (int i = 0; i < arr_num; ++i)
        {
            if (sum >= 0)
                sum += arr[i];
            else
                sum = arr[i];
            if (sum > temp_ans)
                temp_ans = sum;
            dp_s[i] = temp_ans;
        }

        temp_ans = INT_MIN, sum = 0;
        for (int i = arr_num - 1; i >= 0; --i)
        {
            if (sum >= 0)
                sum += arr[i];
            else
                sum = arr[i];
            if (sum > temp_ans)
                temp_ans = sum;
            dp_r[i] = temp_ans;
        }

        ans = dp_s[0] + dp_r[1];
        for (int i = 1; i < arr_num - 1; ++i)
        {
            int sum = dp_s[i] + dp_r[i + 1];
            if (sum > ans)
                ans = sum;
        }
        printf("%d\n", ans);
    }

    return 0;
}

 

你可能感兴趣的:(poj)