在最大m子段和問題中,要求取m個互不相交子段,和為最大值。最大m子段和問題是最大子段和在子段個數上的推廣,最大子段和問題是m=1的特殊情況。
在這個問題中,我們使用乙個矩陣b[ i ][ j ],他表示的意義是在前 j 項中被分為 i 段的最大 i 子段和。
首先,既然是前 j 項需要分為 i 段,所以當 i == j 的時候,陣列中的每個數自為一段,此時的值就是前 j 項的和。所以對角線上的值就是前 j 項加起來。
剩下的情況如下圖:
若要確定藍色塊的值,則在黃色塊中尋找乙個最大值,與紅色塊比較,取大者加在自身上。
若是黃色塊,當前值則是乙個新的子段的開始。若是紅色塊,當前值是和前乙個值一起組合成乙個子段的。
若要找分為4段的值,則在第4行找最大值即可。
因為所有值是通過左上方或左方而來,所以為了節省時間和空間,可以將b矩陣按如下簡化:
**如下:
def
max_sum_3
(m, n, a)
:if n < m or m <1:
return
b =for i in
range(0
, m +1)
:)for j in
range(0
, n +1)
: b[i]0)
for i in
range(1
, m +1)
:for j in
range
(i, n - m + i)
:if j > i:
b[i]
[j]= b[i]
[j-1
]+ a[j]
for k in
range
(i -
1, j)
:if b[i]
[j]< b[i-1]
[k]+ a[j]
: b[i]
[j]= b[i-1]
[k]+ a[j]
else
: b[i]
[j]= b[i-1]
[j-1
]+ a[j]
sum=
0for j in
range
(m, n +1)
:ifsum< b[m]
[j]:
sum= b[m]
[j]return
sum
跟最大子段和問題類似,在最大子段和問題中,只用到了b[j]和b[j-1],因此只使用乙個b來節約空間。同樣地,在最大m子段和問題中,只使用了j行和j-1行,因此使用兩個陣列即可。
更改後的**如下:
def
max_sum_4
(m, n, a)
:if n < m or m <1:
return
b =c =
for i in
range(0
, n - m +1)
:0)0
)for i in
range(0
, m)
: b[0]
= c[0]
+ a[i]
for j in
range(1
, n - m +1)
: b[j]
= b[j -1]
+ a[i + j]
for k in
range(0
, j +1)
:if b[j]
< c[k]
+ a[i + j]
: b[j]
= c[k]
+ a[i + j]
for j in
range(0
, n - m +1)
: c[j]
= b[j]
sum=
0for i in
range(0
, n - m +1)
:ifsum< b[i]
:sum
= b[i]
return
sum
動態規劃 最大m子段和
繼最大子段和在空間上的推廣,那麼再來看看她在個數上的延伸。最大子段和就是最大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 ...
最小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 ...