HDU 1003 Max Sum

9 篇文章 0 订阅
9 篇文章 0 订阅

这是一道动态规划的题目,刚学了一点动态规划还不太熟悉,这一道题研究了很久才做出来

题目大意:
输入n个数字,其中的数字可以按排列顺序相加,找出相加值最大的子序列,输出该最大值和起点终点

思路:
该题使用dp来做,整体的思路根据 max{dp[i]+sum, dp[i]} 来判断, 数字相加不是一遇到负数就停止相加,而是直到发现之前相加的结果成了负数为止。
我们可以设置变量ans存储最终的结果、变量temp暂时存储目前相加得到的结果,同时要记录是从第几个数开始相加,到第几个数停止,每相加一次后temp都会改变,如果temp大于ans就更新结果。
这是一个边记录最大值边尝试的过程,每一次temp大于ans时更新最大值。当dp[i]是一个正数时相加后temp肯定会更大所以就毫不犹豫继续往后相加;当dp[i]是一个负数时相加后temp肯定会变小,但只要temp仍然不是一个负数,即是暂时变小了一些但通过之后的相加还是有可能变得更大,所以我们要给dp[i]<0一个机会,j继续往后相加,希望让之后的数来弥补减去的这部分,就算之后不断相加temp还是没有减小之前大也没关系,因为在ans中已经存放了最大的情况。如果temp一直与负数相加最后可能会变成一个负数,此时下一个数就算是一亿,相加后temp会变成一个很大的数,但仍然比一亿小,负数的部分对这个一亿来说却是一个累赘,远不如直接舍弃之前的所有数,从一亿重新开始向后相加。

完整代码如下:

#include<stdio.h>
int main() {
    int t, n ;
    int data[100005] ;
    int temp, ans, first, last, x, y ;
    scanf("%d", &t) ;
    for(int i=1; i<=t; i++) {
        scanf("%d", &n) ;
        for(int j=0; j<n; j++)
            scanf("%d", &data[j]) ;
        x = y = first = last = temp = 0 ;
        ans = -1000000 ;
        for(int j=0; j<n; j++) {
            if(temp+data[j] >= data[j]) {   //只有temp为负数时再加多大的数都不如直接从新的数开始
                temp += data[j] ;
                last = j ;
            }
            else {
                temp = data[j] ;        //从新的点开始计
                first = last = j ;
            }
            if(temp > ans) {            //更新结果
                ans = temp ;
                x = first ;				//开始
                y = last ;				//停止
            }
        }
        printf("Case %d:\n", i) ;
        printf("%d %d %d\n", ans, x+1, y+1) ;	//因为从0开始所以要加一
        if(i < t)
            printf("\n") ;
    }
    return 0 ;
}

总结:
dp不好搞。。。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值