**:揹包九講
有揹包容量為v,n個物品,每個重量為w[i],價值為v[i],每個物品僅有一件,要使得揹包價值最大怎麼裝物品?
定義dp陣列含義:dp[i][j]表示考慮前i個物品在揹包容量恰為j的情況下達到的最大價值。
狀態轉移方程:
f[i][j]=max(f[i−1][j],f[i−1][j−w[i]]+v[i])
解釋:針對第i個物品有兩種選擇,一是放進揹包,一是不放進揹包。max中的第一項就是不放進揹包,那麼就轉換為考慮前i-1件物品放進容量為j的揹包;第二項是放進揹包,問題轉化為前i-1件物品放入容量為j-w[i]的揹包,此時的最大價值是再加上當前的物品的價值。
使用滾動陣列的思想:
for (int i = 1; i <= n; i++)//遍歷物品for (int j = v; j >= 0; j--)//遍歷容量
f[j] = max(f[j], f[j - w[i]] + v[i]);
外層遍歷物品,內層要從大到小遍歷,因為物品最多只能取一次。(完全揹包問題中是從小到大遍歷容量,因為可以取無限次。)
只要數量有限制都只能從大到小遍歷,其實從原始公式中看的更明顯,從大到小只保證使用的是i-1的計算結果。
總結:如果容量從小到大遍歷,那麼就會重複計算物品,使用的是之前計算的結果,針對完全揹包問題;那麼針對01揹包問題,就需要從後往前,就不會重複計算包了。
力扣例題:416. 分割等和子集
有揹包容量為v,n個物品,每個重量為w[i],價值為v[i],每個物品有無數件,要使得揹包價值最大怎麼裝物品?
dp陣列含義和上面相同,按照每個物品可取數量可以這麼寫,
f[i][j]=max(f[i−1][j−k∗w[i]]+k∗v[i])∣0<=k∗w[i]<=j
但是不好解。
for (int i = 1; i <= n; i++)//遍歷物品for (int j = w[i]; j <= v; j++)//遍歷容量
f[j] = max(f[j], f[j - w[i]] + v[i]);
遍歷物品,但揹包容量是從小到大的,因為物品可以無限次使用。
兩層for迴圈可以替換?
舉例:322. 零錢兌換
for(int i=1;i<=amount;i++)}for(int i=0;i)
}
377. 組合總和 ⅳ,完全揹包問題,求組合數,結果可以重複,所以是對物品的排列,需要先遍歷容量,再遍歷物品。
* 1.0-1揹包問題,外層遍歷物品,內層從大到小遍歷容量;(因為只能用一次)
* 完全揹包問題,外層便利物品,內層從小到大遍歷容量。(能用多次)
70. 爬樓梯,如果本題用揹包思想來做,因為是排列問題,不是組合問題,所以需要遍歷容量,如果遍歷物品的話,那麼物品的順序是定的,就出現方法數變少的錯誤。
!!!錯誤的**!!!class
solution ;
vector
dp(n+1,0
); dp[
0]=1
;
for(int i=0;i)
}return
dp[n];
}};
//正確的**:
class
solution3 ;
vector
dp(n+1,0
); dp[
0]=1
;
for(int i=1;i<=n;i++)
}return
dp[n];
}};
每件物品多了個數量限制。
//還沒有做過這樣得的題目。
有的可以取0-1次,有的可以取無限次,有的能取k次。
那麼針對0-1和完全可以分開求解:
p[i]:每個物品的件數,0代表無窮個for (int i = 1; i <= n; i++)//
遍歷物品
if (p[i] == 0)//
完全揹包問題
for (int j = w[i]; j <= v; j++)//
從小到大遍歷
f[j] = max(f[j], f[j - w[i]] +v[i]);
else
for (int k = 1; k <= p[i]; k++)//
如果p[i]是1,就是0-1揹包問題,否則是多重揹包問題
for (int j = v; j >= w[i]; j--)
f[j] = max(f[j], f[j - w[i]] + v[i]);
//還沒有做過這樣的題目,希望做的時候能想到解法。
現在物品有兩種重量,兩種價值,當然也有兩個揹包,也就是有兩個限制,那麼就再多加一維狀態:
定義dp陣列含義:dp[i][j][k]表示考慮前i件物品,揹包容量分別為j和k時能達到的最大價值。
狀態轉移:
max(f[i−1][j][k],f[i−1][j−w[i]][k−g[i]]+v[i])//不放、放
那麼此時就需要從大到小遍歷:
for (int i = 1; i <= n; i++)for (int j = v; j >= w[i]; j--)//兩層均需要從大到小遍歷
for (int k = t; k >= g[i]; k--)
f[j][k] = max(f[j][k], f[j - w[i]][k - g[i]] + v[i]);
時間複雜度就是三層for迴圈乘積了,空間複雜度降成了二維。
題目:474. 一和零
揹包問題 01揹包總結
寫這篇部落格的原因是因為自己初學揹包的時候覺得好玄學。只是知道怎麼寫,但是具體是為什麼覺得很玄妙。在此其實希望和我一樣的小白萌新早點明白其中的原理,其實原理很簡單,只要懂了這個圖,我想01揹包就不成問題了。首先要明確這張表是至底向上,從左到右生成的。關於01揹包的題目暫時整理了一點。1.簡單01揹包...
揹包問題總結
標籤 acm dp 揹包 n 物品,乙個揹包,每個物品價值wi 體積vi 揹包容量 c 求最大價值 對於物品 i可選可不選 fi j fi 1 j vi j 0 fi j max c j vi 給定 n 種物品和乙個揹包。第 i種物品的價值是 wi 其體積為vi 揹包的容量為 c 同一種物品的數量無...
揹包問題總結
揹包問題主要是分為三種 0 1揹包,完全揹包,多重揹包 1 0 1揹包 定義 何謂0 1揹包,可以這樣想,那裡有一堆值錢的東西,每一樣東西只有一件,他們的價值和體積都不一樣,現在要你從這n件裡面挑選一些放到乙個容量一定的揹包裡面,使得你的揹包裡的東西總價值最大。對於這些東西的每一件,你可以選擇放進你...