HDU-1231 最大连续子序列

HDU-1231 最大连续子序列

Time Limit : 2000/1000ms (Java/Other)
Memory Limit : 65536/32768K (Java/Other)

Problem Description

给定K个整数的序列{ N1, N2, …, NK },其任意连续子序列可表示为{ Ni, Ni+1, …,
Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个, 例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和 为20。 在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该 子序列的第一个和最后一个元素。

Input

测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( < 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。

Output

对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元 素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。

Sample Input

6
-2 11 -4 13 -5 -2
10
-10 1 2 3 4 -5 -23 3 7 -21
6
5 -8 3 2 5 0
1
10
3
-1 -5 -2
3
-1 0 -2
0

Sample Output

20 11 13
10 1 4
10 3 5
10 10 10
0 -1 -2
0 0 0


题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1231

分析

题意:题意我就不多做解释了,应该都可以看懂。

思路:很明显的要用到DP,求出最大的和不难,难的是如何标记出来首尾元素。首先先将DP代码写出来,注意最好不要缩写,要将整个步骤都写出来,这样才会直到在哪里更新。关键的一些代码我已经注释了,方便大家理解。

代码

#include 
#include 
#include 
using namespace std;
int num[10005];
int dp[10005];
int n;
void DP()
{
    int sum; // 用来标记最大值
    int x,y,z;
    sum=x=y=z=dp[1]=num[1]; // 将各个数字初始化。
    for (int i=2;i<=n;i++)
    {
        if (dp[i-1]+num[i]>num[i])
         // num[i]小于前面求出的最大和,继续加上。
            dp[i]=dp[i-1]+num[i];
        else  // num[i]大于前面求出的最大和,进行更新。
        {
            dp[i]=num[i];
            z=num[i];
        }
        if (sum// 出现当前最大值大于标记的最大值
        {
            sum=dp[i];
            x=z;  // z表示首位元素
            y=num[i]; // y表示末位元素
        }
    }
    // 之所以要用x,z两个变量来标记首位元素,是因为有一些特殊情况不能直接标记,就比如说0、-2,
这个时候z更新了,但是首位元素却是不能更新的。这一点是比较难以理解的,你可以手动实现一下这个步骤。
    if (sum<0)
        cout<<'0'<<" "<1]<<" "<else
        cout<" "<" "<int main()
{
    while (~scanf("%d",&n),n!=0)
    {
        memset(dp,0,sizeof(dp));
        for (int i=1;i<=n;i++)
            cin>>num[i];
        DP();
    }
    return 0;
}

你可能感兴趣的:(ACM__动态规划)