動態規劃 揹包問題降維以及衍生的硬幣問題

2021-07-13 06:25:13 字數 1313 閱讀 1330

任何動態規劃核心就是劃分子問題,然後就是狀態轉移方程。中間求出來的子問題的解需要儲存起來。

0-1 揹包問題解決的是物品只能夠選擇1次要不就不選,在揹包能夠裝得下的前提下面,能夠保證裝的價值最大:

狀態轉移方程 f[i][j] = max; 0≤

j - wi≤j

用二維的空間來表示是比較簡單的

一維表示:f[v] 表示 f[i][v] , 那麼由於上面的這個公式:

f[i][j] = max; 

可以發現f[i][j] 的值只是和f[j-1][j] , 和f[i-1][j-wi] ,如果我們寫出如下的**:

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

那麼對於i = n 的情況,我們計算 vec [j] 時, 由於j-wi < j ,那麼

vec[j-w[i]]的值會在vec[j]後參與計算,所以,在計算vec[j ] 的時候,我們先讀取到的vec[j] 實際上是vec[n-1][j] , 讀取到的vec[j-w[i]]實際上是vec[n-1][j-w[i]],所以可以用上面的公式進行簡化。

完全揹包問題中每個物品都可以選擇無限多次

從上面的公式中可以看出來,f(i , j)只會和f(i-1, j )還有f(i,j-wi)兩個變數有關,外層的i是從0開始累加的,我們考慮i=n的這次迴圈情況。此時,j將會從0

開始累加,

那麼,我們計算f( j )的步驟如下 :  

首先讀取到的f( j ) , 一定是f( n-1 , j ) (因為我們的外層計算中的 i 是從0開始加的)

然後我們會讀取f(j-wi),因為這個j-wi<j, 所以f(i-wi)的值已經經過了計算,表示的是f(n,j-wi)

到這裡,我們只需要將f( j )和f(j-wi)取max,求出來的值用來更新f(j),此時的f(j)就是f(n,j)了。至此,二維空間將為一維。

生成**就是

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

}硬幣問題和完全揹包問題類似,原

題是這樣的:

有1分,2分,5分,10分四種硬幣,每種硬幣數量無限,給定n分錢,有多少中組合可以組成n分錢?

採用動態規劃的思路,f(i,j)表示的是可以取的0,1,...,i種硬幣的情況下,湊夠j元一共有多少種方法。

遞推公式以及相應的一維如何推導為二維如下:

降維原因和完全揹包類似。

動態規劃的降維

01揹包問題 有n件物品和乙個容量為c的揹包。第i件物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。w i 表示物品i的重量 v i 表示物品i的價值 c 表示揹包的容量 dp i c 表示前i件物品恰放入乙個容量為c的揹包可以獲得的最大...

動態規劃 揹包問題

給定n個物品,重量是,價值是,包的容量 承重 是w 問,放入哪些物品能使得包內價值最大 1 需要將問題轉化為子問題,通過遞迴實現,且子問題必然與父問題存在關聯 2 定義v i,j 表示為,當item取自前i個items且揹包capacity j 時,揹包問題的最優解,也即最高的價值。3 從前i個it...

動態規劃 揹包問題

不廢話,直接上 動態規劃,揹包問題。輸入為 int n 物品的種類數。int n weight 各件物品的重量。int n value 各種物品的價值。int w 揹包最大的裝載重量。輸出 v n b 的值,最大的裝載價值。x n 各類物品的裝載數量。author huangyongye publi...