您的位置:首页 > 其它

POJ2479 - Maximum sum (动规)

2015-08-30 01:39 260 查看
题目链接 : poj2479 - Maximum sum


思路
最大连续子列和

代码

思路

题目要求的是,两段不相交的连续子列,使其加和最大。基础问题就是最大连续子列和,只要分别求得正序和逆序的最大和,然后枚举一边中间点,就可以得到结果。

最大连续子列和

解法有多种,这里用一种比较简单的动规的方法。另一种思路

令 num[i]num[i] 表示序列中第 i 个数字, F(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(1) = num[1] \
\begin{cases}
\ F(i) = F(i-1) + num[i],\ \ \ \ F(i-1)>0 \\
\ F(i) = num[i],\ \ \ \ F(i-1)<=0
\end{cases}

根据题意,我们需要的 F(i)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
= num
;
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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: