码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1003 dp(最大子段和)

时间:2015-02-11 21:52:39      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

题意:给出一列数,求其中的最大子段和以及该子段的开头和结尾位置。

因为刚学过DP没几天,所以还会这题,我开了一个 dp[100002][2],其中 dp[i][0] 记录以 i 为结尾的最大子段的和, dp[i][1] 记录以第 i 个数 A[i] 为结尾的和最大子段的开始位置。

对于每一个数 A[i] :

我考察它的前一个数 A[i-1] ,若以 A[i-1] 为结尾的最大子段和 dp[i-1][0] 大于等于 0 ,那么在这个基础上加上 A[i] ,一定大于等于 A[i] 本身,所以以第 i 个数结尾的最大子段就是以第 i-1 个数结尾的最大子段加上第 i 个数,以此更新 dp[i] ;

而若 dp[i-1][0] 小于 0 ,那么在这个子段的基础上加上 A[i] ,一定小于 A[i] 本身,所以以第 i 个数为结尾的和最大子段就是这个数本身,所以 dp[i] 也就可以这样得到了。

当遍历一遍数列之后,再求最大的 dp[i][0] ,输出 dp[i][0] 、 dp[i][1] 和 i 即可。

 

#include<stdio.h>
int A[100002];
long long dp[100002][2];
int main(){
    int T;
    while(scanf("%d",&T)!=EOF){
        long long N,q;
        for(q=1;q<=T;q++){
            scanf("%I64d",&N);
            long long i,ans,stx,edx=1;
            for(i=1;i<=N;i++)scanf("%d",&A[i]);
            printf("Case %I64d:\n",q);
            ans=dp[1][0]=A[1];
            stx=dp[1][1]=1;
            for(i=2;i<=N;i++){
                if(dp[i-1][0]>=0){
                    dp[i][0]=dp[i-1][0]+A[i];
                    dp[i][1]=dp[i-1][1];
                }
                else{
                    dp[i][0]=A[i];
                    dp[i][1]=i;
                }
            }
            for(i=1;i<=N;i++){
                if(dp[i][0]>ans){
                    ans=dp[i][0];
                    stx=dp[i][1];
                    edx=i;
                }
            }
            printf("%I64d %I64d %I64d\n",ans,stx,edx);
            if(q!=T)printf("\n");
        }
    }
    return 0;
}

hdu1003 dp(最大子段和)

标签:

原文地址:http://www.cnblogs.com/cenariusxz/p/4286982.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!