繼最大子段和在空間上的推廣,那麼再來看看她在個數上的延伸。
最大子段和就是最大m子段和問題在m=1時的特殊情況
類似最大欄位和中的b(j)
這裡假設b(i,j)表示陣列a的前j項中i個子段和的最大值,且第i個子段含a[j]
其中b(i,j-1)+a[j]表示第i個子段含a[j],而
初始時b(0,j)=0,(0<=j<=n);b(i,0)=0,(1<=i<=m)
int maxsum(int m,int n,int *a)
,這樣的b[i][j]才能表示最大i欄位和b[i][j]=b[i-1][k]+a[j];
}else //i==j的情況
b[i][j]=b[i-1][j-1]+a[j];
int sum=0;
for( j=m;j<=n;j++)
if(sum
例如:a= m=3
根據以上演算法段可得出下表,表中藍色表示初始化,紅色xx表示不存在i>j的情況,即b(i,j)不合實際,紫色o表示該字段僅含乙個元素,
例如b(i,j),i=1時,j最多只能為6,然後a[7],a[8]各為乙個子段,這樣才能構成m=3的子段
重點是綠色數字,表示經過了更新的值。例如綠色2,此時i=2,j=3,根據b(i,j-1)+a[j]=-1+2=1,然後從i-1~j-1,也就是1~2,maxb(i-1,t)+a[j]=0+2=2 由於2>1,所以更新b(2,3)=2
再比如說綠5,1(-1+2)->5(3+2) 綠26,25(12+13)->26(13+13) 綠16,12(1+11)->16(5+11).......
最後在b(3,j)中找最大值,即1,16,12,29,24,24,中,找出29為最大3子段和
演算法分析:由此可知該演算法時間複雜度為o(m*n^2),空間複雜度為o(m*n)
但是經分析可知計算b[i][j]時只用到了陣列b的第i-1行和i行的值,因而演算法只要儲存b的當前行i和i-1行,沒必要儲存整個二維陣列的值。
改進後演算法如下:
int maxsum(int m,int n,int *a)
c[i+n-m]=max;//當然在一輪結束的時候c也是要儲存當前最大子段和max
cout<
printa(b,n);
cout<
printa(c,n);
cout<
執行結果:
紅色圓點表示:c被更新的地方,
紅色斜槓表示:某個子段首個成員更新的情況,如b[1]=3-->c[0]=3,這是直接更新的,但是在計算出b[2]=-1,先是直接賦值c[2],因為此時的最大欄位和就是上一次的3嘛,但有所不同的是,這裡我會將max和當前最大欄位和b[j]比較一下,然後更新,用於下一次的c[j-1]
由此可知該演算法的時間複雜度o(m(n-m),空間複雜度為o(n),當m或者n-m為常數時,時間複雜度便可降為o(n)
動態規劃 最大m子段和
在最大m子段和問題中,要求取m個互不相交子段,和為最大值。最大m子段和問題是最大子段和在子段個數上的推廣,最大子段和問題是m 1的特殊情況。在這個問題中,我們使用乙個矩陣b i j 他表示的意義是在前 j 項中被分為 i 段的最大 i 子段和。首先,既然是前 j 項需要分為 i 段,所以當 i j ...
最小m子段和(動態規劃)
問題描述 給定n個整數組成的序列,現在要求將序列分割為m段,每段子序列中的數在原序列中連續排列。如何分割才能使這m段子序列的和的最大值達到最小?輸入格式 第一行給出n,m,表示有n個數分成m段,隨後一行給出n個數,以空格分隔 輸入樣例 9 39 8 7 6 5 4 3 2 1 輸出樣例 解釋 9 8...
最大m子段和
最大m子段和問題 給定由n個整數 可能為負 組成的序列a1 a2 a3.an,以及乙個正整數m,要求確定序列的m個不想交子段,使這m個子段的總和最大!設b i,j 表示陣列a的前j項中i個子段和的最大值,並且第i個子段包含a j 1 i m,i j n 則所求的最優值為maxb m,j m j n ...