![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> using namespace std; int maxleft=0,maxright=0;//记录最大字段和起点和终点 int MaxSubsum(int *a,int left,int right){ int sum=0; if(left==right) sum=a[left]>0?a[left]:0; else{ int center=(left+right)/2; int leftsum=MaxSubsum(a,left,center); int rightsum=MaxSubsum(a,center+1,right); int i,j; int s1=0; int lefts=0; for(i=center;i>=left;i--){//注意 :i的值是从center开始递减,不是从left开始递增 lefts+=a[i]; if(lefts>s1) { s1=lefts; maxleft=i;//记录最大字段和的最左边 } } int s2=0; int rights=0; for(j=center+1;j<=right;j++){ rights+=a[j]; if(rights>s2) { s2=rights; maxright=j;//记录最大字段和的最右边 } } sum=s1+s2; if(sum<leftsum) { sum=leftsum; if((right-left+1)%2==0)//如果最大字段和在左边,那么记录它的右边位置 maxright=center; else maxright=center-1; } if(sum<rightsum) { sum=rightsum; maxleft=center+1;//如果最大字段和在右边,那么记录它的左边位置 } } return sum; } int main(){ int n,a[100]; cout<<"n:"; cin>>n; a[0]=0; cout<<"请输入 "<<n<<" 元素:"; for(int i=1;i<=n;i++) cin>>a[i]; int max=MaxSubsum(a,1,n); cout<<"最大的和是"<<max<<endl; cout<<"从第"<<maxleft<<"位置"<<"--> 第"<<maxright<<"位置相加"<<endl; int i; for(i=maxleft;i<maxright;i++) cout<<a[i]<<"+"; cout<<a[i]<<"="<<max<<endl; return 0; }
所给的序列a[1:n]的分为a[1:n/2]和a[n/1+1:n],分别求出这两段的最大字段和,则a[1:n]的最大字段和与三情形
1.a[1:n]的最大字段和与a[1:n/2]的最大字段和相同
2.a[1:n]的最大字段和a[n/2+1:n]的最大字段和相同
3.a[1:n]的最大字段和为ai+..ak
第三种情况可以看出a[n/2]和a[n/2+1]在最优子序列中,因此,可以在a[1:n/2]中计算出s1=max(a[i]+..+a[n/2]),并在a[n/2+1:n]中计算出s2=max(a[n/2+1]+..+a[j])