题目链接:HAUTOJ 1266
方法一:根据最大连续子列和问题可以改编成每次加两个数,注意因为奇数长度需要有两个开始项,从第一个开始(奇数项开始),和从第二项开始(偶数项开始),还需要注意加a[i+1]时更新sum,即把a[i+2]作为第一项
方法二:加一个数列b,第一二项分别为a的一二项,从第三项开始b[i]=b[i-2]+a[i-1]+a[i],b[i]表示从第一项到当前项的奇数长度的和,如果b[i]<a[i]的话,表示前面为负值,更新开始项
方法一
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int a[100005],max1,max2,max0,i,j,k,n,sum;
cin>>n;
cin>>a[1];
max0=a[1];
for(i=2;i<=n;i++)
{
cin>>a[i];
if(a[i]>max0)max0=a[i];//寻找数组中最大元素
}
if(max0<0||n<3)
{
cout<<max0<<endl;
continue;
}
max1=a[1];//两种情况,一是从奇数列开始的最大奇数子列和,一是从偶数列开始
sum=a[1];
for(i=1;i+2<=n;i+=2)//每次加两个,保证奇数长度
{
sum+=a[i+1];//注意这地方加上第一个元素的时候不变成0
if(sum<0)sum=0;//这时候才变成0,保证奇数列
sum+=a[i+2];
if(sum>max1)max1=sum;//更新最大和
}
max2=a[2];
sum=a[2];
for(i=2;i+2<=n;i+=2)
{
sum+=a[i+1];
if(sum<0)sum=0;
sum+=a[i+2];
if(sum>max2)max2=sum;
}
max0=max(max1,max2);
cout<<max0<<endl;
}
return 0;
}
方法二
#include <bits/stdc++.h>
using namespace std;
int a[100005],b[100005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
if(n==1)
{
printf("%d\n",a[0]);
}
else if(n==2)
{
printf("%d\n",max(a[0],a[1]));
}
else
{
b[0]=a[0],b[1]=a[1];//b[i]表示从第一项到当前项的奇数长度的和
int Max=max(a[0],b[0]);
for(int i=2;i<n;i++)
{
b[i]=max(a[i],b[i-2]+a[i-1]+a[i]);//每次加两个,如果为负值的话,a[i]更新为当前项,即第一项
if(b[i]>Max)//更新最大值
Max=b[i];
}
printf("%d\n",Max);
}
}
}