#include <stdio.h>

int main()
{
    int a[110000], dp[110000];
    int i, j, k, t, n, begin, end, temp, max;
    
    scanf("%d", &t);       //共有t组测试实例。
    for(k=1; k<=t; k++)
    {
        scanf("%d", &n);
        for(i=1; i<=n; i++)
            scanf("%d", &a[i]);

        dp[1] = a[1];            //dp[i]数组存放的是,以i为终点的最大子序列和。
        begin = 1;                //begin end记录起始与结尾下标。
        end = 1;
        temp = 1;                //重点:记录每个重新开始的子序列的起始下标。(后面会详细介绍)
        max = dp[1];            //max 存放 和最大子序列。

        for(i=2; i<=n; i++)
        {
            if(a[i] > dp[i-1]+a[i])        //状态转移方程:dp[i] = max(dp[i-1]+a[i] , a[i]) 是指取二者中的最大值。
            {
                dp[i] = a[i];
                temp = i;                //temp 当a[i] > dp[i-1]+a[i]成立时dp[i]的开始下标会更新。
            }
            else
                dp[i] = dp[i-1] + a[i];

            if(dp[i] > max)
            {
                max = dp[i];
                end = i;
                begin = temp;
            }
        }
        
        printf("Case %d:\n%d %d %d\n", k, max, begin, end);
        if(k!=t)                                            //注意格式问题。
            printf("\n");
    }

    return 0;
}
/*******************************************************************************************************
这是一道典型的动态规划题(DP),下面以一实例进一步解释。如序列{6,-1,-3,-1,6,8}
dp[1] = 6, dp[2] = 5(因为dp[1]+a[1] > a[1],下面也是一样), dp[3] = 2, dp[4] = 1, dp[5] = 7, dp[6] = 15.
 begin = 1, end = 6.
DP问题中最关键的是找到状态转移方程。这题状态转移方程为dp[i] = max(dp[i-1]+a[i] , a[i])
若仍然不太理解 加我QQ:836939432
********************************************************************************************************/

/* ********************************************
作者:桂思
时间:2013年12月7日 20:04:42
用途:求和最大子序列。
******************************************** */

posted on 2013-12-07 20:19  桂思  阅读(160)  评论(0)    收藏  举报