最大连续子序列
题目描述
给定K个整数的序列{ N1, N2, …, NK },其任意连续子序列可表示为{ Ni, Ni+1, …, Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20。现在增加一个要求,即还需要输出该子序列的第一个和最后一个元素。
输入描述
测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( K< 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。
输出描述
对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。
#include<iostream>
// #include<math.h>
using namespace std;
const int maxn=10000;
int arr[maxn];
int dp[maxn];
int k;
void maxsequence(int n){
if(n==1){
cout<<arr[0]<<' '<<arr[0]<<' '<<arr[0]<<endl;
return ;
}
int sum=0,max1=arr[0],before=0,end=0;
dp[0]=arr[0];
if(arr[0]<0)sum++;
for(int i=1;i<n;i++){
dp[i]=max(arr[i],arr[i]+dp[i-1]);
if(arr[i]<0)sum++;
if(max1<dp[i]){
max1=dp[i];
end=i;
}
}
if(sum==n){
cout<<0<<' '<<arr[0]<<' '<<arr[n-1]<<endl;
}else{
int i=end;
while(dp[i]>=0&&i>-1)i--;
cout<<max1<<' '<<arr[++i]<<' '<<arr[end]<<endl;
}
}
int main(){
while(cin>>k){
if(k==0)break;
for(int i=0;i<k;i++){
cin>>arr[i];
}
maxsequence(k);
}
return 0;
}
关键点总结:
常规的动态规划求得最大子序列之和plus了要输出序列的首尾元素之和,方法就是再maximal变化的时候记录最后一个元素的下标,然后倒推到第一个不为负数的地方。