您的位置:首页 > 其它

动态规划之最大子段和问题

2017-11-21 19:16 281 查看
有一由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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划