【POJ】poj 2479 (DP_优化)

本文介绍了一个经典动态规划问题——最大子数组和问题,并提供了一种高效算法解决方案。该算法利用两个数组分别记录从前向后和从后向前的最大子数组和,最终通过遍历找出整个数组中的最大和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Language:Default

Maximum sum

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 33010 Accepted: 10205

Description

Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
Your task is to calculate d(A).

Input

The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input. 
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.

Output

Print exactly one line for each test case. The line should contain the integer d(A).

Sample Input

1

10
1 -1 2 2 3 -3 4 -4 5 -5

Sample Output

13

Hint

In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer. 

Huge input,scanf is recommended.

 

这是一个动态规划的问题可以用一个数组表示fro[ i ] 表示前 i 个数字里面最大和的序列,其中可能不包括 i (这样就简化了查找最优解的复杂度降了一阶,不然会超时到哭),用另外一个数组backs[ i ] 表示从 i 个数字到结尾中包括 i 的最大和,可以再最后用一个循环求出最大值,

 

代码如下:

 

#include<iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
int num, maxsum;
int allsum[50005],fro[50005],backs[50005];
/*
inline int frodp( int i )
{
    if ( fro[i] != 0 ) return fro[i];
    if ( frodp( i - 1 ) > 0 ) fro[i] = fro[i-1] + allsum[i];
    else fro[i] = allsum[i];
    return fro[i];
}
inline int backdp( int j )
{
    if ( backs[j] != 0 ) return backs[j];
    if ( backdp( j + 1 ) > 0 ) backs[j] = backs[j+1] + allsum[j];
    else
        backs[j] = allsum[j];
    return backs[j];
}*/
int main()
{
    int test;
    cin >> test;
    while ( test > 0 )
    {
        test--;
        cin >> num;
        for ( int i = 0; i < num; i++ )
        {
            scanf("%d",&allsum[i]);
        }
        memset(fro,0,sizeof(fro));
        memset(backs,0,sizeof(backs));
        fro[0] = allsum[0];
        backs[num-1] = allsum[num-1];
        int ans = -100000;
        for ( int i = 1; i <= num-1; i++ )///计算包括第i个数的和的最大值;
        {
            if ( fro[i-1] > 0 )
                fro[i] = fro[i-1] + allsum[i];
            else
                fro[i] = allsum[i];
        }
        for ( int j = num-2; j >= 0; j-- )///计算后j个数字,包括j的和的最大值;
        {
             if ( backs[j+1] > 0 )
                backs[j] = backs[j+1] + allsum[j];
            else
                backs[j] = allsum[j];
        }
        for ( int i = 0; i < num - 1; i++ )
            fro[ i + 1 ] = max ( fro[i],fro[i+1] );///表示第i个数字以前最大和,可以是不包括i的,这样就可以在下面减少一层循环;
        for ( int i = 0; i < num - 1; i++ )
        {
            //for ( int j = num - 1; j > i; j-- )
            //{
                if ( ans < fro[i]+ backs[i+1])
                    ans = fro[i]+ backs[i+1];
            //}
        }
        printf("%d\n",ans);
    }
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值