主题思想:最大连续子序列,最大连续子序列是和最大的连续子序列,
这是一个经典的dp问题。
dp[i] 表示以i结尾的连续子序列的和
对于第i个数字,或者选择加入前面的序列,此时dp[i]=dp[i-1]+a[i],或者本身作为一个单独的序列,此时dp[i]=a[i]。
dp[i]=max(a[i],dp[i-1]+a[i])
即,如果dp[i-1]+a[i]>a[i] 则选择a[i]加入以前的序列。否则自己成为一个单独的序列。 移项得dp[i-1]>0
最后遍历一遍,找出最大的连续子序列和。
如果需要记录子序列的开头位置,则需要新开一个数组s,s[i] 用来表示以i个元素结尾的,连续子序列的开头位置,
当dp[i-1]>0时 ,dp[i]=dp[i-1]+a[i] ,s[i]=s[i-1]
当dp[i-1]<=0 时,dp[i]=a[i] s[i]=i
AC代码:
#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=10005;
int dp[maxn]; //dp[i] menas the max sum of sequence end with i
int s[maxn]; // s[i] remember the start index i of the sequence stands by dp[i]
int a[maxn];
int main()
{
int k;
while(scanf("%d",&k)!=EOF){
if(k==0) break;
int m=0;
for(int i=1;i<=k;i++){
scanf("%d",&a[i]);
if(a[i]<0)m++;
}
if(m==k){
printf("0 %d %d\n",a[1],a[k]);
continue;
}
dp[1]=a[1];
int mx=dp[1];
for(int i=2;i<=k;i++){
if(dp[i-1]>0){
dp[i]=dp[i-1]+a[i];
s[i]=s[i-1];
}else{
dp[i]=a[i];
s[i]=i;
}
}
int start=1,e=1;
for(int i=2;i<=k;i++){
if(dp[i]>mx){
mx=dp[i];
e=i;
start=s[i];
}
}
printf("%d %d %d\n",mx,a[start],a[e]);
}
return 0;
}