思路
题目要求的是,两段不相交的连续子列,使其加和最大。基础问题就是最大连续子列和,只要分别求得正序和逆序的最大和,然后枚举一边中间点,就可以得到结果。
最大连续子列和
解法有多种,这里用一种比较简单的动规的方法。另一种思路
令
num[i]
表示序列中第 i 个数字,
F(i)
为以第 i 个数字结尾的序列中最大的和, 那么
F(1)=num[1] { F(i)=F(i−1)+num[i], F(i−1)>0 F(i)=num[i], F(i−1)<=0
根据题意,我们需要的
F(i)
是第 i 个数字之前的连续子列和的最大值,我们需要从头到尾更新一次
for(int i=2; i=n; i++) f(i) = max( f(i), f(i-2) );
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
const int inf = 0x7ffffff;
using namespace std;
int num[50010], s[50010], e[50010];
int main()
{
int t, n, maxsum, sum;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i=1; i<=n; i++) scanf("%d", num+i);
s[1] = num[1];
for(int i=2; i<=n; i++)
{
if(s[i-1]>0) s[i] = s[i-1] + num[i];
else s[i] = num[i];
}
for(int i=2; i<=n; i++) s[i] = max(s[i], s[i-1]);
e[n] = num[n];
for(int i=n-1; i>=1; i--)
{
if(e[i+1]>0) e[i] = e[i+1] + num[i];
else e[i] = num[i];
}
for(int i=n-1; i>=1; i--) e[i] = max(e[i+1], e[i]);
maxsum = -inf;
for(int i=1; i<n; i++)
{
sum = s[i] + e[i+1];
if(sum>maxsum) maxsum = sum;
}
printf("%d\n", maxsum);
}
}

本文讨论了最大连续子列和问题的基础解决方法,并将其扩展应用到求解两段不相交的连续子列使加和最大。通过动态规划,首先解决最大连续子列和问题,然后通过枚举中间点,最终得到最优解。
&spm=1001.2101.3001.5002&articleId=48098385&d=1&t=3&u=bf12f41f98f940ceb21d54366836be1f)
712

被折叠的 条评论
为什么被折叠?



