题目大意:
现有多个测例(测例数题中给出),对于每个测例都会给定一序列,长度为N(2 ≤ N ≤ 5,000),序列中每个元素的范围为[-10000, 10000],对于每个测例都输出序列中两个不相交子段的和的最大值,子段必须是连续的。
注释代码:
/*
* Problem ID : POJ 2479 Maximum sum
* Author : Lirx.t.Una
* Language : C++
* Run Time : 422 ms
* Run Memory : 720 KB
*/
#include <stdio.h>
//表示数组中元素的无穷小值
#define RINF -10001
//序列的最大长度
#define MAXN 50001
#define MAX(x,y) ( (x) > (y) ? (x) : (y) )
int a[MAXN];//array,表示序列,下标从1开始
//lft[i]和rht[i]在初始化时表示以i为右边界和左边界的子序列的最大和
//在动态规划时将会被跟新为
//以i为右边界和左边界的子序列的最大和
int lft[MAXN], rht[MAXN];
int
main() {
int t;//测例数
int n;//元素个数
int i;//技术变量
int tmp;//临时变量
int ans;
scanf("%d", &t);
while ( t-- ) {
scanf("%d", &n);
for ( i = 1; i <= n; i++ )
scanf("%d", a + i);
//序列最大不相交子段和等于左序列最大子段和右序列最大子段之和
//对左序列初始化
lft[1] = a[1];
for ( i = 2; i <= n; i++ )
if ( lft[i - 1] <= 0 )//若以i - 1号元素为右边界的子序列和小于0
lft[i] = a[i];//则直接将lft[i]初始化为a[i]即可,此时该序列只有i一个元素
else
lft[i] = lft[i - 1] + a[i];//否则在之前序列基础上加上该元素
//由于任何子段都肯定有一个末尾(边界)元素,因此根据这点
//将lft[i]更新为最大子段和
for ( i = 2; i <= n; i++ )//此时lft[i - 1]已经被更新成以i - 1有右边界的左序列
//的最大和,而lft[i]还是之前的以i为右边界的子序列的和
lft[i] = MAX( lft[i - 1], lft[i] );
//有序列同理
rht[n] = a[n];
for ( i = n - 1; i >= 1; i-- )
if ( rht[i + 1] <= 0 )
rht[i] = a[i];
else
rht[i] = rht[i + 1] + a[i];
for ( i = n - 1; i >= 1; i-- )
rht[i] = MAX( rht[i + 1], rht[i] );
for ( ans = RINF, i = 1; i < n; i++ ) {//根据断点的不同
//找出具有最大不相交子段和的分法
tmp = lft[i] + rht[i + 1];
ans = MAX( ans, tmp );
}
printf("%d\n", ans);
}
return 0;
}
无注释代码:
#include <stdio.h>
#define RINF -10001
#define MAXN 50001
#define MAX(x,y) ( (x) > (y) ? (x) : (y) )
int a[MAXN];
int lft[MAXN], rht[MAXN];
int
main() {
int t;
int n;
int i;
int tmp;
int ans;
scanf("%d", &t);
while ( t-- ) {
scanf("%d", &n);
for ( i = 1; i <= n; i++ )
scanf("%d", a + i);
lft[1] = a[1];
for ( i = 2; i <= n; i++ )
if ( lft[i - 1] <= 0 )
lft[i] = a[i];
else
lft[i] = lft[i - 1] + a[i];
for ( i = 2; i <= n; i++ )
lft[i] = MAX( lft[i - 1], lft[i] );
rht[n] = a[n];
for ( i = n - 1; i >= 1; i-- )
if ( rht[i + 1] <= 0 )
rht[i] = a[i];
else
rht[i] = rht[i + 1] + a[i];
for ( i = n - 1; i >= 1; i-- )
rht[i] = MAX( rht[i + 1], rht[i] );
for ( ans = RINF, i = 1; i < n; i++ ) {
tmp = lft[i] + rht[i + 1];
ans = MAX( ans, tmp );
}
printf("%d\n", ans);
}
return 0;
}