HDU1003 Max

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
题目大意:最大子段和,求连续的ai中和最大的
题目思路:这道题想明白了很简单,一个简单的动态规划。所有的子数列,可以按照“以a[i]为结尾”的规则分成n组
第一组为a[1],
第二组为a[1],a[2] 与a[2]
第三组为a[1],a[2],a[3]与a[2],a[3]与a[3]
……
我们要求的最大值,只要将这n组的最大值求出,然后再求出n个最大值中的最大值即可。
记dp[i]为第i组的最大值,那么
dp[1] = max{a[1]} = a[1];
dp[2] = max{a[1] + a[2], a[2]} = max{dp[1] + a[2], a[2]};
dp[3] = max{a[1] + a[2] + a[3], a[2] + a[3], a[3]}= {dp[2] + a[3], a[3]};
……
则可归纳出dp[i] = max{dp[i - 1] + a[i], a[i]};(其中1 ≤ i ≤ n)
接下来要求始末位置,
仔细一想,当我们取最大值取得是dp[i - 1] + a[i]的时候,始位置不变,末位置变成了i,当我们取a[i]时,始末位置都变成了i。
然后题目要求取第一个出现的最大值,那么if(dp[i - 1] + a[i] > a[i]) 的等号要取。

#include<cstdio>
#include<cstring>
const int maxn = 100004;
int a[maxn];
int dp[maxn];
int main()
{
    int n;
    scanf("%d", &n);

    for(int i = 1; i <= n; i ++)
    {
        if(i != 1){
            printf("\n");
        }
        memset(a, 0, sizeof(a));
        int t;
        scanf("%d", &t);
        int maxx = -100000;
        int ff = 1,ll = 1;
        int first = 1, last = 1;
        for(int j = 1; j <= t; j ++)
        {
            scanf("%d", &a[j]);

            if(j == 1)
            {
                dp[j] = a[j];
            }
            else
            {

                if(dp[j - 1] + a[j] >= a[j]){
                    dp[j] = dp[j - 1] + a[j];
                    last = j;
                }
                else {
                    dp[j] = a[j];
                    first = j;
                    last = j;
                }

            }
            if(dp[j] > maxx)
            {
                maxx = dp[j];
                ff = first;
                ll = last;
            }
        }

        printf("Case %d:\n%d %d %d\n", i,maxx,ff,ll);
    }
}
posted @ 2018-03-20 23:37  asakuras  阅读(88)  评论(0编辑  收藏  举报