有一由n个整数组成的序列A={a1,a2,…an,},求该序列如
a[i]+a[i+1]+…+a[j]的子段和的最大值。如果序列中全部是负数则最大子段和为0,依此定义,所求的最优值max{0,a[i]+a[i+1]+…+a[j]},1≤i≤j≤n。
输入:n //序列的长度
序列值
输出:最大子段和
例如:
输入:
6
-2,11,-4,13,-5,-2
输出:
20
算法可通过动态规划求解:
我们用b[j]来记录以j为结尾的子段和集合中的最大值。
举个例子:假如有一个序列:-2,11,-4,13,-5,-2有:
a[1]=-2, a[2]=11, a[3]=-4, a[4]=13, a[5]=-5, a[6]=-2;
b[1]=-2, b[2]=11, b[3]=7, b[4]=20, b[5]=15, b[6]=13;
b[1]<0, b[2]>0, b[3]>0, b[4]>0, b[5]>0, b[6]>0;
递推关系:
b[j]=Max(b[j-1]+a[j], a[j]) //b[j]表示以j结尾的字段和集合中的最大值
由此可写出如下代码:
#include<iostream>
using namespace std;
int a[100];
int b[100];
int Max(int a,int b);
int getMaxSum(int a[],int n,int &begin,int &end);
//a[] 存储序列
//n 序列长度
//begin end 开始、结束的位置
int main(){
int begin=-1,end=-1;
int maxSum;
int n;
cout<<"请输入序列的长度:"<<endl;
cin>>n;
cout<<"请输入序列:"<<endl;
for(int i=1;i<=n;i++){
cin>>a[i];
}
maxSum=getMaxSum(a,n,begin,end);
cout<<"最大字段和为:"<<maxSum<<endl;
cout<<"开始位置为:"<<begin<<endl;
cout<<"结束位置为:"<<end<<endl;
return 0;
}
int getMaxSum(int a[],int n,int &begin,int &end){
int max=0;
for(int i=1;i<=n;i++){
b[i]=Max(a[i],b[i-1]+a[i]);
if(max<b[i]){
max=b[i];//保存在最大值中
end=i;//记下end的值
}
}
for(int i=end;i>=0;i--){//回溯法求起始位置
if(b[i]=a[i]){
begin=i;
}
}
return max;
}
int Max(int a,int b){
if(a>=b){
return a;
}
else
return b;
}