1003 最大连续子序列

来源:互联网 发布:十香cosplay淘宝 编辑:程序博客网 时间:2024/06/15 13:28

最大连续子序列

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 56   Accepted Submission(s) : 25
Problem Description
给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., <br>Nj },其中 1 &lt;= i &lt;= j &lt;= K。最大连续子序列是所有连续子序列中元素和最大的一个, <br>例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和 <br>为20。 <br>在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该 <br>子序列的第一个和最后一个元素。<br>
 

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

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

Sample Input
6-2 11 -4 13 -5 -210-10 1 2 3 4 -5 -23 3 7 -2165 -8 3 2 5 01103-1 -5 -23-1 0 -20
 

Sample Output
20 11 1310 1 410 3 510 10 100 -1 -20 0 0<div style='font-family:Times New Roman;font-size:14px;background-color:F4FBFF;border:#B7CBFF 1px dashed;padding:6px'><div style='font-family:Arial;font-weight:bold;color:#7CA9ED;border-bottom:#B7CBFF 1px dashed'><i>Hint</i></div>Hint</div>Huge input, scanf is recommended.


          这题题意简单明了,就是一个最大连续字段和问题,他的前身就是简单动态规划,方法上也是一个式子解决:dp【i】=max{dp【i-1】+a【i】,0};初始状态设置为

dp【i】=max{a【i】,0}。

          然而这题稍微难了一点,让同时求出来字序列的首位元素。我的思路是尾元素肯定是知道的,在最后循环找最大字段和的时候,找的的地方就是尾元素的位置。所以要求的就只是一个首元素,而首元素遵循这么一个原则:如果满足dp[【i1】+p【i】>0,那么字段和是加上前面已经求的,所以首元素也是原来的首元素,即 i-1 时的首元素。 反之的话,下标等于下一个元素的下标(i+1),因为已经确定了这个数和之前的数都不是最大字段和的了。


代码如下:



#include<iostream>
#include<cstring>
using namespace std;
int maxx(int a,int b)
{
    if(a>b)
        return a;
    return b;
}
int main()
{
    int n;
    int p[10010];
    int dp[10010][2]; //dp[][0]代表字段和  dp[][1]代表该出的首元素的下表
    while(cin>>n&&n)
    {
        memset(p,0,sizeof(p));
        memset(dp,0,sizeof(dp));
        int flag=0;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i];
            if(p[i]>=0)
                flag=1;
        }
        if(flag==0)         //小优化,也是一步处理,如果都小于0的情况
        {
            cout<<"0 "<<p[1]<<" "<<p[n]<<endl;
            continue;
        }
        if(p[1]>0)
        {
            dp[1][0]=p[1];
            dp[1][1]=1;
        }
        else
        {
            dp[1][0]=0;
            dp[1][1]=2;
        }
        for(int i=2;i<=n;i++)
        {
            if(dp[i-1][0]+p[i]>0) //如果满足条件
            {
                dp[i][0]=dp[i-1][0]+p[i]; //得到字段和
                dp[i][1]=dp[i-1][1];  //得到首元素下标  等于之前的
            }
            else  //反之
            {
                dp[i][0]=0;
                dp[i][1]=i+1;     //首元素坐标为下一个数的下标  因为 该数和之前的数都确定排除了,只能从下一个开始
            }
        }
        int maxx=0,cnt=0;
        for(int i=1;i<=n;i++)
        {
            //cout<<dp[i][1]<<" ";
            if(maxx<dp[i][0])
            {
                maxx=dp[i][0];
                cnt=i;
            }
        }
        cout<<dp[cnt][0]<<" "<<p[dp[cnt][1]]<<" "<<p[cnt]<<endl;
    }
    return 0;
}


原创粉丝点击