HAUTOJ 1266: 最大子段和 河工大校赛DP

**1266: 最大子段和

题目描述

一个大小为n的数组a1到an(−10^4≤ai≤10^4)。请你找出一个连续子段,使子段长度为奇数,且子段和最大。

输入

第一行为T(1≤T≤5),代表数据组数。
之后每组数据,第一行为n(1≤n≤10^5),代表数组长度。
之后一行n个数,代表a1到an。

输出

每组数据输出一行,表示满足要求的子段和最大值
样例输入

1
4
1 2 3 4
样例输出

9**

题目很容易读懂,就不叙述题意了
主要思路:
1:数组num存储前i项连续的子段和,如果子段和num[i]小于0,则将第i项的值dp[i]存入第i项子段和num[i]中
2:数组num2存储前i项连续且长度为奇数的子段和,同时更新最大值

#include<stdio.h>
#include<string.h>
#define N 100000
int num[N+10],num2[N+10],dp[N+10];
int main()
{
    int i,j,n,t,si,max;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));
        memset(num2,0,sizeof(num2));
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for( i = 1; i <= n; i ++)
            scanf("%d",&dp[i]);

        num[1] = dp[1];
        /*思路步骤1*/
        for( i = 2; i <= n; i ++)
        {
            if(num[i-1] + dp[i] < 0)
                num[i] = dp[i];
            else
                num[i] = dp[i]+num[i-1];
        }
        num2[1] = num[1];
        max = -10010;
        si = 1;
        /*思路步骤2*/
        for( i = 1; i <= n; i ++)
        {
            if(num[i-1] + dp[i] < 0)
                si = i;
            if((i-si)%2 != 1)
                num2[i] = num[i] ;
            else
                num2[i] = num[i] - dp[si];
            if( max < num2[i])
                max = num2[i];
        }
        printf("%d
",max);
    }
    return 0;
 } 

后记:杭电的1003和这道题很类似,只不过多了一个判断长度奇偶的条件,自己优化时,导致WA的一个地方,是在判断起始条件处,改为了前i项连续且长度为奇数的子段和num2[i]是否小于0。
dp题自己现在写着很焦灼,还是得多思考+刷题,翻阅其他博客,发现还有另外一个比较好方法,等自己理解了再更。

原文地址:https://www.cnblogs.com/hellocheng/p/7350166.html