如何運用動態規劃解題

2022-04-05 16:32:45 字數 2835 閱讀 6580

本文內容整理自中國大學mooc郭煒老師的程式設計與演算法(二)

首先由數字三角形問題出發( ̄︶ ̄)↗ ,題目描述如下

7 3   8 

8   1   0 

2   7   4   4 

4   5   2   6   5

在上面的數字三角形中尋找一條從頂部到底部的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或右下走。只需要求出這個最大和即可,不必給出具體路徑。(三角形的行數大於1小於100,數字為0~99)

輸入:

第一行是數字三角形的行數,接下來 n 行是數字三角形中的數字。  

比如:5

73  8

8 1 0

2 7 4 4

4 5 2 6 5  

輸出:

最大和分析:

1)首先最容易想到的是遞迴演算法,第n行第n列到底部的路徑最大和為:自身+第n+1行最大的;臨界條件:最後一行的路徑最大和即為自身。

遞迴參考**

///

遞迴#include using

namespace

std;

intn;

int maxsum(int i,int j,int a[101

]);int

main()

}cout

<0,0

,a);

return0;

}int maxsum(int i,int j,int a[101

])else

if(i1

)}

2)可是該遞迴方法有很多很多重複的計算,所以我們想到可以記下已經算過的,當用到時直接拿過來用,這樣就避免了大量的重複運算。

///

記憶遞迴型動規

#include using

namespace

std;

intn;

int b[101][101];//

記憶陣列用來存已經計算出來的結果

int maxsum(int i,int j,int a[101

]);int

main()

}cout

<0,0

,a);

return0;

}int maxsum(int i,int j,int a[101

])else

else

if(i1

)

}}

3)其實呢,一般都是用遞推的方式來推出動態規劃演算法的,用迴圈遞推不但比遞迴快,而且還能節省空間,寫起來也比較方便,但是還是基於遞迴的思想才能遞推出遞推式。

第一步:在草稿紙或者腦子裡想出解決該題的遞迴函式。

第二步:遞迴函式有n個引數,就定義乙個n維的陣列,陣列的下標是,遞迴函式引數的取值範圍,陣列元素的值是遞迴函式的返回值。

第三步:根據邊界條件,初始化n維陣列。

第四步:得到遞推式,根據遞推式逐步填充陣列,相當於遞迴的逆過程。

如本題:

///

第一步寫遞迴函式已經在上面寫完了

#include #include

using

namespace

std;

intmain()

}///第三步根據邊界條件初始化二維陣列

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

/**第四步,根據遞迴函式推出遞推式

a[i][j],i==n-1;

dp[i][j]=

max(dp[i+1][j],dp[i+1][j+1])+a[i][j];

*////

得到遞推式,把遞推式寫出來

for(int i=n-1;i>=1;i--)

}cout

<1][1]

}

4)往往由遞推式寫出的程式可以進行空間優化,如樣例輸入

①用一維記憶陣列代替多維記憶陣列

其一維記憶陣列為maxsum=

那麼算n-1行經過2的路徑的最大和,在4和5中選出最大數,將結果存在4的位置,即maxsum=。這樣並不會影響其他的路徑和,比如第n-1行經過7的路徑的最大和,是在5和2中選出最大數。

#include #include 

using

namespace

std;

intmain()

}for(int i=1;i<=n;i++)

for(int i=n-1;i>=1;i--)

}cout

<1]

}

②刪去一維記憶陣列,用儲存輸入資料的陣列的最後一行當作記憶陣列儲存計算結果

#include #include 

using

namespace

std;

intmain()

}//因為一維記憶陣列初始化是和d陣列第n行一樣,而且d陣列第n行只在n-1才會用到

for(int i=n-1;i>=1;i--)

}cout

<1]

}

4)那麼什麼樣的問題適合用動態規劃呢?

①問題具有最優子結構性質。

如果問題的最優解所包含的子問題的解也是最優的,我們就稱該問題具有最優子結構性質。  

②無後效性。

當前的若干狀態的值一旦確定,則此後過程的演變就只和這若干個狀態的值有關,和之前是採取哪種手段或經過哪條路徑演變到當前的這若干個狀態,沒有關係。

動態規劃解題思路

在leetcode上看題解與結合自己的想法得出思路。首先明確 dp 陣列所存資料的含義。這步很重要,如果不得當或者不夠清晰,會阻礙之後的步驟。然後根據 dp 陣列的定義,假設 dp 0 i 1 dp 0 i 1 都已知,想辦法求出 dp i dp i 一旦這一步完成,整個題目基本就解決了。但如果無法...

動態規劃解題思路

一直以來,對動態規劃的理解處於乙個模糊的狀態,就是一種似乎懂但遇到問題未必能行的狀態 然後,最近重點在leetcode上找了一些動態規劃的題目做了一下,逐漸有了一些思路。我覺得leetcode上對動態規劃思想的概括非常到位,所以記錄在這裡 動態規劃 英語 dynamic programming,簡稱...

動態規劃解題步驟

動態規劃解題步驟?給你兩個單詞 word1 和 word2,請你計算出將 word1 轉換成 word2 所使用的最少運算元 你可以對乙個單詞進行如下三種操作 插入乙個字元 刪除乙個字元 替換乙個字元 示例 1 輸入 word1 horse word2 ros 輸出 3 解釋 horse rorse...