HDU 1003 max sum

Max Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 204001    Accepted Submission(s): 47699


Problem Description
Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
 

Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
 

Output
For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
 

Sample Input
  
  
2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5
 

Sample Output
  
  
Case 1: 14 1 4 Case 2: 7 1 6
 

Author
Ignatius.L



题目大意:


给出测试组数,第一行是测试数据的个数,然后是每个测试数据。

输出要求,输出连续子序列最大和,并且输出这个连续子序列的起始位置和终止位置。


思路:


每个数的选择只有两种,加或者不加,对吧?加的话就更新子序列下标,不加的话就重置。

每次加或者不加都会产生一种状态。每次只需要决策加或者不加,所有的最优决策就组成了最优解。

为了方便大家理解,首先我们来给出一组数据:

    5     1    2    3    -6     6 

也就是说 有  5   个数,分别为  1   2   3   -6   6   

然后求出他的最大连续子序列的和。

开始  sum =  0  。        左边是加上下个数,右边是不加下个数。   枝点是 sum 的值。             

                  begin

                                                     /                                          \

                                                   1                                             0

                                       /                 \                                         /      \

                                      3                    0                                   2          0

                                 /      \                /       \                            /   \       /   \

                                6        0             3        0                        5    0    3     0

                             /      \    /     \       /    \      /   \                 /    \   / \   /  \   /  \

                            0    0    -6       0   - 3      0   -6    0          -1   0   -6  0 -3 0  -6  0

最后一层就不写了。。。

注意看,你们发现了什么吗?

第一层, 1  和   0  

           从 1  走下去肯定比从 0  走下去得到的和大。

           第二层 从  3   走下去得到的和 肯定也是最大的,

所以建树的过程就可以这样简化 :

                                      begin

                                     /        \

                                    1           0

                                  /     \

                               3           0

                            /      \

                          6        0

/   \

                      0       0

                   /      \

                  6         0

由此我们可以看出最大值为 6  ,那么,怎么写程序模拟这个建树的过程呢?

               

int sum,maxsum,first,last;
        sum=0;
        maxsum=-1001;
        first=1;
        for (i=1;i<=n;i++)
        {
            sum += a[i];
            if (sum > maxsum)
            {
                maxsum=sum;
                last=i;
            }
            if (sum <0)
            {
                sum=0;
                first=i+1;
            }
        }

上面的代码,可以读一下。每次都将值加入进来,如果  sum  <  0  就更新数据,如果比之前的大 就更新最大值并且记录下标。


感想:


好了,这个题看了好久,上面是我的一些见解,希望有助于大家理解动态规划,可能有的人要问 了,这个也是动态规划吗?怎么没有状态转移方程呢?

其实吧,动态规划又何尝不是一种思想呢?非要有状态转移方程吗?

不见得。(或许是我还刚接触  dp   在胡言乱语。但是希望,上面的东西有助于你们理解 dp )


AC代码:


#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
    int j,i,k,n,m,t;
    int a[100002];
    scanf("%d",&t);
    for (j=1;j<=t;j++)
    {
        scanf("%d",&n);
        for (i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        int sum,maxsum,first,last;
        sum=0;
        maxsum=-1001;
        first=1;
        for (i=1;i<=n;i++)
        {
            sum += a[i];
            if (sum > maxsum)
            {
                maxsum=sum;
                last=i;
            }
            if (sum <0)
            {
                sum=0;
                first=i+1;
            }
        }

        printf("Case %d:\n%d %d %d\n",j,maxsum,first,last);
        if (j!=t)
        {
            printf("\n");
        }
    }

    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值