ACM第三專題 動態規劃總結

2021-07-12 07:13:06 字數 2563 閱讀 4641

一.概述

動態規劃的基本思想:若要解乙個給定問題,我們需要解其不同部分(即子問題),再合併子問題的解以得出原問題的解。 通常許多子問題非常相似,為此動態規劃法試圖僅僅解決每個子問題一次,從而減少計算量: 一旦某個給定子問題的解已經算出,則將其

記憶化儲存,以便下次需要同乙個子問題解之時直接查表。 這種做法在重複子問題的數目關於輸入的規模呈

指數增長

時特別有用。

三大重要性質:

最優子結構性質:

如果問題的最優解所包含的子問題的解也是最優的,我們就稱該問題具有最優子結構性質(即滿足最優化原理)。最優子結構性質為動態規劃演算法解決問題提供了重要線索。

子問題重疊性質:

子問題重疊性質是指在用遞迴演算法自頂向下對問題進行求解時,每次產生的子問題並不總是新問題,有些子問題會被重複計算多次。動態規劃演算法正是利用了這種子問題的重疊性質,對每乙個子問題只計算一次,然後將其計算結果儲存在乙個**中,當再次需要計算已經計算過的子問題時,只是在**中簡單地檢視一下結果,從而獲得較高的效率。

無後效性

:將各階段按照一定的次序排列好之後,對於某個給定的階段狀態,它以前各階段的狀態無法直接影響它未來的決策,而只能通過當前的這個狀態。換句話說,每個狀態都是過去歷史的乙個完整總結。這就是無後向性,又稱為無後效性。

二.分類解析

1.最長遞增子串行.

例題:題意:給出序列a [1], a [2], a [3] ...... a [n],計算子串行的最大總和。

思路:最大子串行是要找出由數組成的一維陣列中和最大的連續子串行。方法是:只要前i項和還沒有小於0子串行就一直往後擴充套件,否則丟棄之前的子串行開始新的子串行,同時記錄各個子串行的和,最後取他們中的最大值。

**:#include#include

using namespace std;

int main()

else      

else before+=now;

}if(before>max)

max=before,s=x,e=i;

}printf("case %d:\n%d %d %d\n",ca++,max,s,e);

if(t)printf("\n");

}return 0;

}2.最長公共子串行.

例題:題意:求兩個字串的最長公共子串行。

思路:動態的方程在第乙個元素的相等的時,dp[0][0] = dp[-1][-1] + 1, 天哪,這肯定就會出錯了。在處理時可以選擇字元的讀取從第乙個位置開始,或者把 i 號字元的狀態儲存到i+1號位置去,這樣就從1號開始處理了,判定是就是 s1[i-1] == s1[j-1] ?

**:#include

#include

#include

#include

#define max( a, b ) (a) > (b) ? (a) : (b)

using namespace std;

char s1[1005], s2[1005];

int dp[1005][1005];

int main()

else}}

printf( "%d\n", dp[len1][len2] );

}return 0;

} 3.揹包問題.

<1>01揹包.

例題:題意:乙個人收集骨頭。給出他的揹包容量和可選的骨頭的體積和價值,輸出他的揹包能裝下的骨頭的最大價值。

思路:01揹包問題,dp公式都類似:f[i;v] = maxff[i-1;v];f[i-1;v-ci] + wi,由這個公式做變形就可以。下面再來分析一下這個公式:

每種骨頭僅有一件,可以選擇放或不放。用子問題定義狀態:即f[i;v] 表示前i 件物品

恰放入乙個容量為v的揹包可以獲得的最大價值。

「將前i 個骨頭放入容量為v的揹包中」這個子問題,若只考慮第i 個骨頭的策略(放或不放),那麼就可以轉

化為乙個只和前i-1個骨頭相關的問題。如果不放第i 個骨頭,那麼問題就轉化為「前i-1個骨頭放入容量為v的

揹包中」,價值為f[i-1; v];如果放第i 個骨頭,那麼問題就轉化為「前i-1個骨頭放入剩下的容量為v-ci 的

揹包中」,此時能獲得的最大價值就是f[i-1;v-ci] 再加上通過放入第i 個骨頭獲得的價值wi。**;

#include

#include

#include

#define m 1009

using namespace std; 

typedef struct pack  

pack;  

int f[m][m];  

int main()

<2>多重揹包.(沒做出來題,只列下思路。)

f[i][v]=max

這跟01揹包問題一樣有o(vn)個狀態需要求解,但求解每個狀態的時間已經不是常數了,求解狀態f[i][v]的時間是o(v/c[i]),總的複雜度可以認為是o(v*σ(v/c[i])),是比較大的。

總結解題一般步驟:

(1)建立模型,確認狀態。

(2)找出狀態轉移方程。

(3)找出初始條件。

第三專題總結(動態規劃)

1.定義 動態規劃是解決多階段決策問題的一種方法,也是一種排除重複計算的演算法,更具體的說,動態規劃就是用空間換取時間。2.動態規劃問題具有以下基本特徵 1 問題具有多階段決策的特徵。2 每一階段都有相應的 狀態 與之對應,描述狀態的量稱為 狀態變數 3 每一階段都面臨乙個決策,選擇不同的決策將會導...

專題三 動態規劃總結

在這篇部落格裡我寫一下做了乙個月的dp之後對dp的粗淺認識,並附上一些學習資源。如果乙個問題的最優解包含其子問題的最優解,我們就稱此問題具有最優子結構。摘自 演算法導論 也就是說,具有最優子結構的問題的最優解一定是由其各個子問題的最優解組合而成的。我覺得dp最關鍵的就是找出狀態轉移方程,即找出問題的...

專題三 總結動態規劃

動態規劃總結 一 解釋 解決多階段策略問題的一種方法,運用最優性原理,排除重複計算,用空間換時間的演算法。二 適用的題目型別 1.問題具有多階段的決策 2.每個階段對應乙個狀態 狀態變數 3.每個階段有乙個決策 不同的決策導致下乙個階段不同的狀態 4.每個階段的最優解可以遞迴地歸結為下乙個階段各個可...