题目来源:点击打开链接
部分图片来源:点击打开链接
-------------------------------------------------------------------------------------------------------
算法1:穷举法
#include<iostream>
using namespace std;
long long MaxSubseqSum1(long long seq[], long long N);
int main()
{
long long N;
long long *p;
cin>>N;
p=new long long[N];
for(long long i=0; i<N; i++)
{
cin>>p[i];
}
MaxSubseqSum1(p, N);
delete []p;
return 0;
}
long long MaxSubseqSum1(long long seq[], long long N)
{
long long maxSum=seq[0];//记录子列和中的最大值
long long thisSum=0;//记录某一子列的和
long long m=0,n=0;
for(long long i=0; i<N; i++)//子列的起始位置 i
{
for(long long j=i; j<N; j++)//子列的结束位置 j
{
thisSum=0;
for(long long k=i; k<=j; k++)//计算所选子列的和
{
thisSum+=seq[k];
}
if(thisSum > maxSum)
{
m=i;//记录更新时,子列和对应的起始位置
n=j;//记录更新时,子列和对应的终止位置
maxSum=thisSum;
}
}
}
if(maxSum>=0)
{
cout<<maxSum<<" "<<seq[m]<<" "<<seq[n];
}
else
{
cout<<0<<" "<<seq[0]<<" "<<seq[N-1];
}
return maxSum;
}
算法2:穷举法(减少部分重复运算)
#include<iostream>
using namespace std;
long long MaxSubseqSum2(long long seq[], long long N);
int main()
{
long long N;
long long *p;
cin>>N;
p=new long long[N];
for(long long i=0; i<N; i++)
{
cin>>p[i];
}
MaxSubseqSum2(p, N);
delete []p;
return 0;
}
long long MaxSubseqSum2(long long seq[], long long N)
{
long long maxSum=seq[0];//记录子列和中的最大值
long long thisSum=0;//记录某一子列的和
long long m=0,n=0;
for(long long i=0; i<N; i++)//子列的起始位置 i
{
thisSum=0;
for(long long j=i; j<N; j++)//子列的结束位置 j
{
thisSum+=seq[j];//计算所选子列的和
if(thisSum > maxSum)
{
m=i;//记录更新时,子列和对应的起始位置
n=j;//记录更新时,子列和对应的终止位置
maxSum=thisSum;
}
}
}
if(maxSum>=0)
{
cout<<maxSum<<" "<<seq[m]<<" "<<seq[n]<<endl;
}
else
{
cout<<0<<" "<<seq[0]<<" "<<seq[N-1]<<endl;
}
return maxSum;
}
算法3:在线方法
#include<iostream>
using namespace std;
long long MaxSubseqSum3(long long seq[], long long N);
int main()
{
long long N;
long long *p;
cin>>N;
p=new long long[N];
for(long long i=0; i<N; i++)
{
cin>>p[i];
}
MaxSubseqSum3(p, N);
delete []p;
return 0;
}
long long MaxSubseqSum3(long long seq[], long long N)
{
long long tempSum=0; //临时记录子列和的变量
long long maxSum=seq[0];//记录子列和的最大值
long long m=0, /*记录起始位置*/
n=0, /*记录终止位置*/
tag=-1;/*记录清零位置*/
tempSum=0;
for(int i=0; i<N; i++)
{
tempSum+=seq[i];
if(tempSum>maxSum)//发现更大子列和则更新maxSum
{
maxSum=tempSum;
n=i;
m=tag+1;
}
else
{
if(tempSum<0)
{
tempSum=0;
tag=i;
}
}
}
if(maxSum>=0)
{
cout<<maxSum<<" "<<seq[m]<<" "<<seq[n];
}
else
{
cout<<0<<" "<<seq[0]<<" "<<seq[N-1];
}
return maxSum;
}
算法4:“分而治之”(递归实现)
#include<iostream>
using namespace std;
class newType
{
public:
long long data;//记录数据
long long index1;//记录首位值
long long index2;//记录末位置
void operator=(newType a)
{
this->data=a.data;
this->index1=a.index1;
this->index2=a.index2;
}
};
newType Max3( newType v1, newType v2, newType v3);
newType _MaxSubseqSum4(long long seq[], long long start, long long end);
newType MaxSubseqSum4(long long seq[], long long N);
int main()
{
long long N;
long long *p;
cin>>N;
p=new long long[N];
for(long long i=0; i<N; i++)
{
cin>>p[i];
}
newType temp;
temp=MaxSubseqSum4(p, N);
cout<<temp.data<<" "<<p[temp.index1]<<" "<<p[temp.index2]<<endl;
delete []p;
return 0;
}
newType Max3( newType v1, newType v2, newType v3)
{
newType temp;
if(v1.data>=v2.data & v1.data>=v3.data)
{
return v1;
}
if(v2.data>=v3.data & v2.data>=v1.data)
{
return v2;
}
if(v3.data>=v1.data & v3.data>=v2.data)
{
return v3;
}
}
newType _MaxSubseqSum4(long long seq[], long long start, long long end)
{
//判断递归是否要结束
if(start==end) //只有一个数字时
{
newType temp;
temp.data=seq[start];
temp.index1=start;
temp.index2=end;
return temp;
}
newType maxSubseqSum_left, /*记录从start到mid范围内的最大子列和 */
maxSubseqSum_right, /*记录从mid+1到end范围内的最大子列和 */
maxSum_left, /*记录以mid为起点向左扫描到start过程中,累加得到的最大和 */
maxSum_right, /*记录以mid+1为起点向右扫描到end过程中,累加得到的最大和 */
maxSubseqSum_cross_mid;/*记录从start到end的范围内,所有包含mid项的子列和的最大值 */
long long mid=0;
mid=(start+end)/2;//得到分割位置
maxSubseqSum_left=_MaxSubseqSum4(seq, start, mid); //计算左边的最大子列和
maxSubseqSum_right=_MaxSubseqSum4(seq, mid+1, end); //计算右边的最大子列和
//计算跨越中间线的最大子列和//
//往左扫描,得到左边最大和
long long tempSum=0;//临时存储变量
maxSum_left.data=seq[mid];
maxSum_left.index1=mid;
maxSum_left.index2=mid;
for(int i=mid; i>=start; i--) /*以mid为起点向左扫描到start过程中,累加得到的最大和 */
{
tempSum+=seq[i];
if(tempSum>=maxSum_left.data)
{
maxSum_left.data=tempSum;
maxSum_left.index1=i;
}
}
//往右边扫描,得到右边最大和
tempSum=0;
maxSum_right.data=seq[mid+1];
maxSum_right.index1=mid+1;
maxSum_right.index2=mid+1;
for(int i=mid+1; i<=end; i++)/*以mid+1为起点向右扫描到end过程中,累加得到的最大和 */
{
tempSum+=seq[i];
if(tempSum>maxSum_right.data)
{
maxSum_right.data=tempSum;
maxSum_right.index2=i;
}
}
maxSubseqSum_cross_mid.data=maxSum_left.data+maxSum_right.data;
maxSubseqSum_cross_mid.index1=maxSum_left.index1;
maxSubseqSum_cross_mid.index2=maxSum_right.index2;
//得到整个序列的最大子列和
return Max3(maxSubseqSum_left, maxSubseqSum_cross_mid, maxSubseqSum_right);
}
newType MaxSubseqSum4(long long seq[], long long N)
{
newType temp;
temp=_MaxSubseqSum4(seq, 0, N-1);
if(temp.data<0)
{
temp.data=0;
temp.index1=0;
temp.index2=N-1;
}
return temp;
}