動態規劃是一種類似於回溯的思想,他通過空間換時間的方法提高效率,一般用於求最優解問題。
在上面我說道,動態規劃其實和回溯很類似。回溯思想在前面的文章我提到過,回溯是一種窮舉可能的方法。
動態規劃則是通過額外的空間將回溯的遞迴樹中不需要的可能提前剪除達到提高效率的目的。
我們來回憶一下回溯能解決的問題的特徵
1、重複子問題(能夠分成乙個乙個重複的階段)
2、無後效性(後面的選擇不會影響前面)
那麼動態規劃能解決什麼問題呢?
1、最優子結構。意思就是說我們的最後的最優解結果是可以通過每乙個階段的最優解一步一步推導出來的。(是不是有點點貪心的味道)回溯為什麼沒有這個?因為回溯是窮舉。
2、無後效性。和回溯一樣,我們在處理某乙個階段的問題是,我們只關心當前階段不需要考慮當前的階段怎麼來的,也不需要考慮後面的階段會不會改變現在的這個階段的狀態。
3、重複子問題,這個最好理解。因為我們把問題的求解過程分割成了乙個乙個子問題,這些子問題重複才更容易處理。
假設我們有乙個4x4的矩陣w。如下圖
每乙個格仔中的數代表相鄰格仔到達這個格仔需要走的距離,我要從左上角走到右下角,每次都只能向右或者向下,求最短路徑。
我們先用回溯的思想去解決這個問題,可以畫出下面這張簡圖。
我使用(x座標,y座標,當前已走距離)的方法表示狀態。
上面這張圖我是窮舉回溯的每個階段的狀態。(重複子問題)
因為我們的目標是最短路徑,也就是說到達相同的位置我只需要走過的路最少的那種方案。
從上面那張圖中我們可以看到有些狀態的x座標,y座標相同但是走過的距離不同,這個時候我們只需要選擇裡面最優解。(最有子結構)如下圖
通過這種剪枝操作,我們能夠介紹絕大部分的無效操作,大大提高效率。
int num_map[4][4] = ;
int status[4][4] = ;
int dynamicprocess()
sum = 0;
//初始化第一列
for (int j = 0; j < 4; ++j)
//因為只能向右或者向下,所以上一步只會來自於當前塊的上或者左邊
//我取二者種的較小值作為上一步。
for (int i = 1; i < 4; ++i) }
}
1、我首先將最優路徑問題分割成了乙個乙個小的最短路徑(重複子問題)
2、在每乙個小的選擇中,我只使用了較短路徑(最優子結構),因為最終的結果一定是多個最短路徑構成
3、我的每一次選擇都不會影響和改變前面的(無後效性),如果說我在後面選擇了某一格仔使得路徑額外+10(大富翁睡眠10分治=。=)。那麼這個問題就不能用動態規劃了。因為後面的結果有了額外的影響。
4、其實我覺得,能用回溯解決的問題,絕大多數都能用動態規劃解決,只不過比較難想到。所以我建議,憑空想象不如用筆畫一畫。
如何理解動態規劃?
long time ago,當我剛看到動態規劃這個響亮的大名時,瞬間陷入了沉思,腦中浮想聯翩,揣摩著這個演算法應該很帶感。查了一下維基百科 不建議你閱讀 動態規劃在尋找有很多重疊子問題的情況的最佳解時有效。它將問題重新組合成子問題。為了避免多次解決這些子問題,它們的結果都逐漸被計算並被儲存,從簡單的...
動態規劃問題二簡單理解
你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。問題解釋 房屋用非...
簡單粗暴地理解動態規劃
動態規劃可以說是做題時比較難以理解的演算法了,我之前也不是很理解,直到在隨機過程中學習了馬爾科夫過程後,再看動態規劃就覺得很簡單了。本文只是幫助簡單粗暴的理解動態規劃,熟練地運用需要親自進行大量的習題練習。一 動態規劃適合解決什麼樣的問題?1 問題具有最優子結構 舉乙個直白易懂的例子 求你走路的時候...