hdu1231 最长连续子序列和

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

  

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

  首先我们会想到n^2的做法就是先求出前缀和,然后枚举最大子序列的起点和终点。但此题数据范围是n<=10000,并且多组数据,所以n^2做法是会超时的。那么应该怎么优化那?

  这道题正解是dp,dp【i】代表以i为结尾的最大子序列和,这样终点是固定的,而起点是随意的,那么我肯定找最优的起点,以2为例,如果第一个元素是正的,那么我一定会加到dp[2]上,如果是负的,那dp[2]最大就是a[2]同样的依次类推,dp[i]就可以求出以i为结尾的最大子序列和,这样如果dp【i-1】是负的,那么dp【i】=a[i](a[i]即原始序列的第i个元素),否则dp[i]=dp[i-1]+a[i],这样最后只需要在扫一遍dp数组就可以知道最大子序列和是多少了。

  本题还要求输出起止两个元素,所以要在处理一下,代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int n;
 5 int a[10005];
 6 int dp[10005];
 7 int s[100005];
 8 int ans;
 9 int t1,t2;
10 int main()
11 {
12     while(1)
13     {
14         scanf("%d",&n);
15         if(n==0)break;
16         ans=-1;
17         for(int i=1;i<=n;++i)scanf("%d",&a[i]),s[i]=s[i-1]+a[i];
18         for(int i=1;i<=n;++i)
19             dp[i]=max(dp[i-1]+a[i],a[i]);
20         t1=1,t2=n;
21         for(int i=1;i<=n;++i)
22             if(dp[i]>ans)ans=dp[i],t2=i;
23         if(t2==n&&ans==-1)
24         {
25             printf("0 %d %d
",a[1],a[n]);
26         }else
27         {
28             for(int i=1;i<=t2;++i)
29                 if(s[t2]-s[i-1]==ans)
30                 {
31                     t1=i;break;
32                 }
33             printf("%d %d %d
",ans,a[t1],a[t2]);
34         }
35     }
36     return 0;
37 } 
原文地址:https://www.cnblogs.com/yuelian/p/11900381.html