最大子段和問題 詳解(C

2021-10-05 18:24:54 字數 3438 閱讀 6125

最大子段和或稱為最大部分和(maximum subtotal)問題,以下簡稱ms。

舉例說明

例如:

暴力破解(brute force):

可以從串的任意位置開始在連續的任意位置結束,一層迴圈控制起始位置,一層迴圈控制結束位置。

複雜度:o(n^2)

//迭代

#include

#include

using

namespace std;

const

int maxnum =

100001

;const

int mininf =

-1000003

;int numn;

int sequence[maxnum]

;int

main()

for(

int i =

1; i <= numn;

++i)

} cout<

<

}return0;

}

動態規劃(dynamic programming):令b[j]表示以位置 j 為終點的所有子區間中和最大的乙個

子問題:如j為終點的最大子區間包含了位置j-1,則以j-1為終點的最大子區間必然包括在其中

如果dp[j-1] >0, 那麼顯然dp[j] = dp[j-1] + seq[j],用之前最大的乙個加上a[j]即可,因為seq[j]必須包含

如果dp[j-1]<=0,那麼dp[j] = seq[j] ,因為既然最大,前面的負數必然不能使你更大

對於這種子問題結構和最優化問題的證明,可以參考演算法導論上的「剪下法」,即如果不包括子問題的最優解,把你假設的解粘帖上去,會得出子問題的最優化矛盾.證明如下:

令seq[x,y]表示seq[x]+…+seq[y] , y>=x

假設以j為終點的最大子區間 [s, j] 包含了j-1這個位置,以j-1為終點的最大子區間[ r, j-1]並不包含其中

即假設[r,j-1]不是[s,j]的子區間

存在s使得seq[s, j-1]+a[j]為以j為終點的最大子段和,這裡的 r != s

由於[r, j -1]是最優解, 所以a[s,j-1]

得到狀態轉移方程:dp[i] = max(seq[i], dp[i-1]+seq[i]) | 1 <= j <= n && dp[i] >= 0;

seq[i] | dp[i] < 0;

例如,若a序列為(-2,11,-4,13,-5,-2),dp[0]=0,求其他元素如下:

(1)dp[1]=max=max=-2

(2)dp[2]=max=max=11

(3)dp[3]=max=max=7

(4)dp[4]=max=max=20

(5)dp[5]=max=max=15

(6)dp[6]=max=max=13

其中,dp[4]=20為最大值,向前找到dp[1]小於等於0,所以由a2~a4的元素即(11,-4,13)構成最大子段和,其和為20

複雜度:o(n),由上式可以看出,如果dp[i]為負數,就沒有在賦能的意義了,所以dp[i]陣列可以不需要,空間複雜度:s(1)。

#include

#include

using

namespace std;

const

int mininf =

-1000003

;int numn;

int maxnum;

intmain()

if(tempsum <0)

maxnum =

max(maxnum, tempsum);}

cout<

}return0;

}

分治(divide and conquer):產生最大子段和可以由三種情況得出:

hint:合併的過程要是連續的

複雜度:t(n) = 2t(n/2) + o(n);即:o(nlgn)

#include

#include

using

namespace std;

const

int maxnum =

100001

;const

int mininf =

-1000003

;int numn;

int sequence[maxnum]

;int

mergemax

(int x,

int y,

int z)

intmaxsum

(int left,

int right)

else

int maxnum2 = mininf;

int tempsum2 =0;

for(

int i = mid+

1; i <= right;

++i)

sum = maxnum1+maxnum2;

sum =

mergemax

(sum, leftsum, rightsum);}

return sum;

}int

main()

cout<<

maxsum(0

, numn)

<

}return0;

}

問題大意:給定乙個矩陣,求最大值子矩陣。

我們可以對矩陣向下疊加轉化為最子段和問題,即當前點為末位邊角元素所有矩陣的最大和:這樣就可以對行不斷向下疊加操作行次求解子段最大和便得到結果。

//poj1050為例

#include

#include

#include

const

int maxnum =

101;

const

int mininf =

-100003

;int dp[maxnum]

;int matrix[maxnum]

[maxnum]

;int numn;

int maxnum;

using

namespace std;

intmain()

if(tempsum <0)

maxnum =

max(maxnum, tempsum);}

}}cout<

}return0;

}

最大子段和詳解

問題的提出 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0,依此定義,所求的最優值為 max,1 i j n 例如,當 a1,a2,a3,a4,a4,a6 2,11,4,13,5,2 時,...

最大子段和詳解

最大子段和問題 maximum interval sum 有時也稱lis 經典的動態規劃問題,幾乎所有的演算法教材都會提到.本文將分析最大子段和問題的幾種不同效率的解法,以及最大子段和問題的擴充套件和運用.一.問題描述 給定長度為n的整數序列,a 1 n 求 1,n 某個子區間 i j 使得a i ...

最大子段和問題

給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0 分治法 分析 首先將陣列分為兩部分,最大子段和 可以在陣列的左半部分也可以在右半部分,也可以橫跨分割點,因此我們只需要用分治思想求出左邊最大...