HDU 1003 max sum

来源:互联网 发布:智能语音翻译软件 编辑:程序博客网 时间:2024/06/08 16:21

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
25 6 -1 5 4 -77 0 6 -1 1 -6 7 -5
 

Sample Output
Case 1:14 1 4Case 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 0