最大子段和——分治与动态规划
生活随笔
收集整理的這篇文章主要介紹了
最大子段和——分治与动态规划
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
問題:
? 給定n個整數(shù)(可能為負數(shù))組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整均為負數(shù)時定義子段和為0,依此定義,所求的最優(yōu)值為:
??
?? ?Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n
??? 例如,當(a1,a2,a3,a4,a4,a6)=(-2,11,-4,13,-5,-2)時,最大子段和為20。
?? ? ?
? 給定n個整數(shù)(可能為負數(shù))組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整均為負數(shù)時定義子段和為0,依此定義,所求的最優(yōu)值為:
??
?? ?Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n
??? 例如,當(a1,a2,a3,a4,a4,a6)=(-2,11,-4,13,-5,-2)時,最大子段和為20。
?? ? ?
?問題求解:
/*簡單算法: **v[0]不保存數(shù)據(jù) **T(n)=O(n^2). */ int MaxSum(int *v,int n,int *besti,int *bestj) {int sum=0;int i,j;for (i=1;i<=n;i++){int thissum=0;for (j=i;j<=n;j++){thissum+=v[j];if (thissum>sum){sum=thissum;*besti=i;*bestj=j;}}}return sum; } /*分治法: **將a[1n]分成a[1n/2]和a[n/2+1n],則a[1n]的最大字段和有三種情況: **(1)a[1n]的最大子段和與a[1n/2]的最大子段和相同 **(2)a[1n]的最大子段和與a[n/2n]的最大子段和相同 **(3)a[1n]的最大子段和為ai++aj,1<=i<=n/2,n/2+1<=j<=n **T(n)=2T(n/2)+O(n) **T(n)=O(nlogn) */ int MaxSum_DIV(int *v,int l,int r) {int k,sum=0;if(l==r)return v[l]>=0?v[l]:0;else{int center=(l+r)/2;int lsum=MaxSum_DIV(v,l,center);int rsum=MaxSum_DIV(v,center+1,r);int s1=0;int lefts=0;for (k=center;k>=l;k--){lefts+=v[k];if(lefts>s1)s1=lefts;}int s2=0;int rights=0;for (k=center+1;k<=r;k++){rights+=v[k];if(rights>s2)s2=rights;}sum=s1+s2;if(sum<lsum)sum=lsum;if(sum<rsum)sum=rsum;}return sum; } /*動態(tài)規(guī)劃算法: **b[j]=max{a[i]++a[j]},1<=i<=j,且1<=j<=n,則所求的最大子段和為max b[j],1<=j<=n。 **由b[j]的定義可易知,當b[j-1]>0時b[j]=b[j-1]+a[j],否則b[j]=a[j]。故b[j]的動態(tài)規(guī)劃遞歸式為: **b[j]=max(b[j-1]+a[j],a[j]),1<=j<=n。 **T(n)=O(n) */ int MaxSum_DYN(int *v,int n) {int sum=0,b=0;int i;for (i=1;i<=n;i++){if(b>0)b+=v[i];elseb=v[i];if(b>sum)sum=b;}return sum; }
總結(jié)
以上是生活随笔為你收集整理的最大子段和——分治与动态规划的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最大字段和 冲出暴力枚举
- 下一篇: 记一次代码优化