/*
* poj 2479 最大和
题目大意:
定义d(A)为如下公式:
d(A) = max{sum(a[s1]..a[t1]) + sum(a[s2]..a[t2]) | 1<=s1<=t1<s2<=t2<=n}
即数组中两个连续子段的和最大值,这两个连续子段之间是不连续的。
解题思路:
本题是最大子段和的变形,其中重要的变化是求两个连续子段的最大和值。同时,这也是
解题的关键所在: 因为t1<s2,所以我们可以采用枚举t1的方式分别求解以t1结尾的子数组
的最大子段和以及以t1+1开头到原数组结尾的子数组的最大子段和值,加和最大的即所求。
数学模型:
f1(i)表示数组a[1..i]中的最大子段和,f2[i]表示a(i..n]数组中的最大子段和,则
f1[i]+f2[i+1]最大的即所求值。
子段和求法见最大子段和问题。-- 1950 二维最大子段和问题
*/
#include <iostream>
#include <cstdio>
namespace {
using namespace std;
const int NEG_INTF = -500000001;
const int N_MAX = 50000;
int a[N_MAX], f1[N_MAX], f2[N_MAX];
}
int main()
{
int t;
scanf("%d", &t);
int n;
for (int i=0; i<t; i++)
{
scanf("%d", &n);
for (int j=0; j<n; j++)
{
scanf("%d", &a[j]);
f1[j] = f2[j] = NEG_INTF;
}
int d, ms1, ms2, ts1, ts2;
d = ms1 = ms2 = ts1 = ts2 = NEG_INTF;
for (int j=0; j<n-1; j++)
{
if (ts1 <= 0)
ts1 = a[j];
else
ts1 += a[j];
if (ts1 > ms1)
ms1 = ts1;
f1[j] = ms1;
if (ts2 <= 0)
ts2 = a[n-1-j];
else
ts2 += a[n-1-j];
if (ts2 > ms2)
ms2 = ts2;
f2[n-1-j] = ms2;
}
for (int j=0; j<n-1; j++)
{
if (f1[j]+f2[j+1] > d) d = f1[j]+f2[j+1];
}
printf("%d\n", d);
}
return 0;
}
// 两次动态规划的结果,没有必要每次都存,仅需存储一次,另外一个动态判断是否是最大值即可
poj 2479 Maximun Sum
最新推荐文章于 2020-04-07 22:53:46 发布