動態規劃求解最大欄位和及其變種問題

2021-12-29 16:21:09 字數 2783 閱讀 1837

動態規劃(dynamic programming, dp)為一常用演算法思想,本文講述如何利用dp解決常見的最大欄位和及其變種問題。

設陣列為a[k],1≤k≤n,最大欄位和x定義為:

x=max1≤i≤j≤n???∑k=ija[k]???

x直觀含義即,求任一連續字陣列的最大和。

不妨設:

b[j]=max1≤m≤j???∑k=mja[k]???

其中,1≤j≤n

b[j]的直觀含義為,以a[j]為結束元素的連續陣列的最大和。

由x和b[j]的定義,易知:

x=max1≤j≤nb[j]

這也很好理解。設想一下,所求得的連續字陣列肯定以某個元素結束,求出所有的「以某個元素結束的連續陣列最大和b[j]」,取其最大的b[j],即為x。

下面求b[j]。

(1) 當b[j−1]>0時,無論a[j]為何值,b[j]=b[j−1]+a[j];

(2)當b[j−1]≤0時,無論a[j]為何值,b[j]=a[j];

k 1

2 3

4 a[k]

3 -4

2 10

b[k]

3 -1

2 12

已知陣列a[k],求b[j],b[j]的含義可以參考上面的定義。通過上述給出的演算法,可以求得b[j]如下。

其中,b[1]=a[1],b[2]=b[1]+a[2],b[3]=a[3],b[4]=b[3]+a[4];因此,對陣列a,最大欄位和為b[4],即x=12。

求x,即最大欄位和的**。

int b[n + 1];

b[1] = a[1];

int x= a[1];

for(int i = 2; i <= n; i++) else

if(b[i] > x)

x = b[i];

}演算法時間複雜度為o(n)。

設陣列a[t],1≤t≤n,兩個不重疊連續字陣列的最大和s定義為:

s=max1≤i≤j

應用了求最大欄位和的方法。其求解演算法如下:

(1)從頭到尾掃瞄一遍陣列,其迴圈下標i從1增加到n,依次求得字陣列a[1…i]的最大欄位和,將結果儲存在maxsum[1…n]陣列;

(2)從尾到頭掃瞄一遍陣列,其迴圈下標i從n減小到1,依次求得字陣列a[i…n]的最大欄位和,將結果儲存在rmaxsum[1…n]陣列;

(3)從尾到頭掃瞄一遍陣列(其實哪個方向無所謂),其迴圈下標從n−1到1,求和maxsum[i]+rmaxsum[i+1],取最大的結果,即max,1≤i≤n−1,即為所要求的結果。

t 1

2 3

4 a[t]

3 -4

2 10

b[t]

3 -1

2 12

maxsum[t]

3 33 12

rb[t]

11 8

12 10

rmaxsum[t]

12 12

12 10

其中,rb陣列與b陣列的作用類似,只不過rb[j]儲存的是「從尾到頭方向,以a[j]元素為結束元素的連續陣列的和的最大值」。而rmaxsum同樣只需根據rb陣列即可求出。

以poj上面2593題「max sequence」為例給出相應的**。

#include

const int max = 100005;

int arr[max];

// 儲存字陣列的最大欄位和,分正向和反向

int maxseqhere[max], rmaxseqhere[max];

// 儲存「以某個元素為結束元素的字陣列」的最大和,同樣分正向和反向

int maxendinghere[max], rmaxendinghere[max];

int main()

// 以下從頭到尾掃瞄陣列,求得字陣列的最大欄位和

maxendinghere[0] = arr[0];

maxseqhere[0] = arr[0];

int maxtemp = arr[0];

for(int i = 1; i < n - 1; i++) else

if(maxendinghere[i] > maxtemp)

maxtemp = maxendinghere[i];

maxseqhere[i] = maxtemp;

}// 以下從尾到頭掃瞄陣列,求得字陣列的最大欄位和

rmaxendinghere[n - 1] = arr[n - 1];

rmaxseqhere[n - 1] = arr[n - 1];

int rmaxtemp = arr[n - 1];

// 儲存輸出結果

int maxsumoutput = rmaxseqhere[n - 1] + maxseqhere[n - 1 - 1];

for(int i = n - 2; i > 0; i--) else

if(rmaxendinghere[i] > rmaxtemp)

rmaxtemp = rmaxendinghere[i];

rmaxseqhere[i] = rmaxtemp;

// 直接在反向掃瞄中求maxsumoutput即可,不用再多一次掃瞄

if(rmaxseqhere[i] + maxseqhere[i - 1] > maxsumoutput)

maxsumoutput = rmaxseqhere[i] + maxseqhere[i - 1];

}printf(%d

, maxsumoutput);

}return 0;

求解最大欄位和

演算法1 窮舉法,對所有的 i,j 對,順序求和a i a j 並比較出較大的和 演算法2 分治法,將陣列分成左右兩半,分別計算左邊的最大和 右邊的最大和 跨邊界的最大和,然後比較其中的最大者。演算法3 動態規劃法 include include 窮舉法求出所有子段和的情況,比較得到較大值 o n ...

最大欄位和求解方法

問題描述 給定n個整數 可能有負數 組成的序列a1,a2,an,求該序列的最大子段和。如果所有整數都是負數,那麼定義其最大子段和為0。方法一 暴力雙重迴圈破解法 方法二 遞迴分治 在陣列的 center right left 2 left 位置處分開。形成兩個子陣列。那麼,最大子段和 可能出現在三個...

暴力法 分治法 動態規劃法求解最大欄位和

實驗專案4 最大子段和問題 發現這個博主的 實在是太棒了 1.問題分析 給定由n個整數 可能有負整數 組成的序列 2.演算法設計思路 暴力法 對於起點 i,遍歷所有長度為1,2,n i 1的子區間和,遍歷所有的字段,找出最大欄位和。分治演算法 求解區間及其最大和,從結構上是非常適合分治法的,因為所有...