動態規劃系列之四梅花樁問題

2022-01-12 14:52:44 字數 3050 閱讀 9621

redraiment是走梅花樁的高手。redraiment總是起點不限,從前到後,往高的樁子走,但走的步數最多,不知道為什麼?你能替redraiment研究他最多走的步數嗎?

例如梅花樁的高度:

2 5 1 5 4 5
結果分析:

6個點的高度各為 2 5 1 5 4 5

如從第1格開始走,最多為3步, 2 4 5

從第2格開始走,最多只有1步,5

而從第3格開始走最多有3步,1 4 5

從第5格開始走最多有2步,4 5

所以這個結果是3

梅花樁問題是最長公升序陣列問題。

使用動態規劃解題,需要題目符合動態規劃的解決思路。動態規劃解題思路是:

將大的問題拆解成小一點問題,小問題和大問題的解決思路是類似的

小問題之間的關係能完成大問題的最優解

通常拆解問題的方法有兩種,一種是二分法,把陣列拆成兩個。第二種是將將陣列逐個遞減,拆解成多個小陣列。對於本體來說,第二種方式比較適合。

小規模問題和大規模問題之間有某種聯絡,這種聯絡就是動態轉移方程。通過小規模問題的解決,能夠解決大規模問題,直到解決最終的問題。

題目是要求陣列 [2,5,1,5,4,5]中最長的公升序陣列。可以按照動態規劃的思路,將大問題拆解成小問題。求6個元素的最長公升序,可以拆解成求5個,同理求5個元素的,可以拆解成求4個。最後一直到1個。

[2,5,1,5,4,5]

[2,5,1,5,4]

[2,5,1,5]

[2,5,1]

[2,5]

[2]

各個小問題之間有一定聯絡,通過找到小問題之間的聯絡,求出最優解。小問題之間的聯絡就是狀態轉移方程。

求最多的步數,但不知道是從哪一步開始算最多。所以就建立乙個陣列dp,陣列dp中儲存從第乙個梅花樁到當前梅花樁的步數。因為求的步數,最少也走一步,所以dp的初始值就是

dp = [1,1,1,1,...1]
當前梅花樁最多的步數,就是拿當前梅花樁逐個和前面的梅花樁比較,當前梅花樁高就比較是比當前小的梅花樁的最大值+1大 還是 該梅花樁本身的值大。通俗來說就是找出梅花樁數值小的。即:

dp[j] + 1 大 還是 dp[i] 大
下標為0時,dp陣列25

1545

1111

11下標為1時,dp陣列。

因為 5 比 2大,所有,dp[0] + 1 > dp[1],所以dp[1]=1+1=225

1545

1211

11下標為2時,dp陣列:

1 < 5, 1< 2,所以dp陣列不變,dp[2] = 125

1545

1211

11下標為3時,dp陣列:

5 > 1,所以dp[3] = max(dp[2]+1,dp[3]) = max(2,1) = 2

同時,5 > 2 ,所以dp[3] = max(2,dp[0]+1) = max(2,2) = 2。

所以dp[3] = 225

1545

1212

11下標為4時,dp陣列:

4 > 1 ,dp[4] = max(dp[4],dp[2]+1) = max(1,2) = 225

1545

1212

21下標為5時,dp陣列:

5 > 4 ,dp[5] = max(dp[5],dp[4]+1) = max(1,3) = 3

5 > 1 ,dp[5] = max(3,1) = 3

5 > 2 ,dp[5] = max(3,1) = 325

1545

1212

23邊界值很清晰就是第乙個梅花樁就一步,也就是dp[1,x,x,x,x,x]

def getresult(l):

n=len(l) # 傳入list的長度

dp=[1]*n # dp[i]表示以第i個樁為結尾,最多走多少步,初始是1步

for i in range(n):# i表示第幾個樁

for j in range(i):# j表示i前面的樁

if l[i]>l[j]: #當第j個樁小於第i個樁的值時,第j個樁有dp[j]個上公升的序列。

dp[i]=max(dp[i],dp[j]+1)#這時比較dp[j]+1和dp[i]大。因為可能會存在比dp[j]更大的序列,所以要找出最大的。

#dp代表下標為i時上公升序列。max找出其中最大的即為所求

return max(dp)

if __name__ == "__main__":

l=[2,5,1,5,4,5]

ans=getresult(l)

print(ans)

梅花樁問題的的巧妙之處在於構建了乙個dp陣列,該陣列中儲存了到下標i最長公升序個數。然後比較arr[i]和arr前面的所有元素的值,如果arr[i]大於前面的元素的值,那麼也就是說arr[i]是公升序的陣列的下乙個元素。但如果arr[i]大於很多個前面的元素的話,就要選擇乙個最大的值,所以迴圈比較i和之前的元素,取乙個最大值。

最大和子陣列最長公升序陣列這兩個問題能代表著陣列類動態規劃的求解方式,兩個問題的相似之處為:

a. 都將問題轉化成以求解第i個元素為結尾的問題

b. 構建dp陣列,填充以第i個元素為結尾的最優解

c. 都將大規模問題拆解成小規模問題

d. 小規模問題小到極限有乙個邊界值,最大和的邊界為只有乙個元素時就是自身,最長公升序的邊界為只有乙個元素時公升序值為1

這四個規律也是求解陣列類動態規劃問題的四個步驟

同時兩個問題也有不同之處:

a. 最大和子陣列,dp陣列中代表著以i為結尾的陣列的最大值,下乙個值只和上乙個值有關,保證連續性

b. 最長公升序陣列,dp陣列中代表這以i為結尾的公升序陣列的個數。下乙個值與前面所有的值都有關聯,要拿到前面值中的最大值。因為其不需要保證連續性,所有需要遍歷前面的dp。最大和子陣列只需要比較前乙個。

動態規劃系列之揹包問題

揹包問題是一類經典問題,經典的揹包九講 推薦部落格。主要有0 1揹包 完全揹包 分組揹包 多重揹包。0 1揹包問題主要場景如下 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i,價值是w i。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。276.柵欄塗色leet...

動態規劃問題系列 Disk Schedule

有很多從磁碟讀取資料的需求,包括順序讀取 隨機讀取。為了提高效率,需要人為安排磁碟讀取。然而,在現實中,這種做法很複雜。我們考慮乙個相對簡單的場景。磁碟有許多軌道,每個軌道有許多扇區,用於儲存資料。當我們想在特定扇區來讀取資料時,磁頭需要跳轉到特定的軌道 具體扇區進行讀取操作。為了簡單,我們假設磁頭...

動態規劃問題系列 word break問題

給定乙個字串和乙個字典,在字串中新增空格來構造乙個句子,使句子中的每個單詞在字典中都存在 輸入 字串 輸出 所有可能的句子 例如 s catsanddog dict cat cats and sand dog 輸出 cats and dog和cat sand dog 將字串分割成2部分s1和s2,如...