01揹包問題部落格

2022-09-19 18:27:12 字數 1861 閱讀 4189

01揹包問題是一種非常經典的動態規劃(\(dp\))的題目。雖然不是很難,但變化靈活,非常重要。

原題是這樣的(稍加改動):

有乙個最多能裝 \(m\) 公斤的揹包,現在有 \(n\) 件物品,它們的重量分別是 \(w_1\),\(w_1\),...,\(w_n\),它們的價值分別為val[1],val[2],...,val[n],求能獲得最大總價值。

動態規劃做題的三大步:

1.定義狀態

2.找出狀態轉移方程

3.找出邊界條件

由於狀態跟容量和物品都有關係,所以dp是二維的。

這道題的狀態就是dp[i][j]是前i個物品放入容量為j的揹包裡所能獲得的最大價值。

狀態轉移方程就很"簡單"了。首先先判斷是否放的下,即if(j>=w[i]),如果放不下,就跟前面一樣的,即dp[i][j]=dp[i-1][j],如果放的下,就max放與不放的價值,即dp[i][j]=max(dp[i-1][j],val[i]+dp[i-1][j-w[i]]),val[i]+dp[i-1][j-w[i]]是因為物品不僅有價值,放進揹包裡還會佔體積。

此題有邊界條件,dp陣列要等於0。

ac**:

#includeusing namespace std;

long long dp[1005][1005],w[1005],val[1005],n,m;

int main()

} cout《注意:j從0開始是因為體積可以為0,輸出dp[n][m]是因為題目說輸出n個物品放入容量為m的揹包裡的最大價值。

類似題目:採藥

01揹包沒有優化前dp陣列是二維,優化後是一維的,具體怎麼優化,先來看乙個**:01

2345

6789

10100

1111

1111

1200

1334

4444

4300

1355

6889

e400

1355

69910

12資料是:

10 40

2 13 3

4 57 9

1234代表前幾個物品,12345678910代表容量。

那麼就會發現dp[i][j]只可能等於d[i-1][j]和dp[i-1][j-1],dp[i-1][j-2]......所以,我們可以倒著迴圈,每一次覆蓋掉前面的。所以可以把物品那一維給去掉,if也可以去掉。

優化**(當作模板背下來就可以啦):

#includeusing namespace std;

long long dp[1005],w[1005],val[1005],n,m;

int main()

dp[0]=1;

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

for(int j=m;j>=w[i];j--)

dp[j]=dp[j]+dp[j-w[i]];

cout《還有些題目有兩個容量,只要定義乙個二維dp就可以了,還要一層迴圈,和第二層迴圈一樣,兩個維度的處理也一樣。

題目:p1507

**(帶注釋):

#includeusing namespace std;

long long dp[405][405],w[505],val[505],v[505],v,w,n;

int main()

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

for(int j=v;j>=v[i];j--)//迴圈體積

for(int k=w;k>=w[i];k--)//迴圈質量

dp[j][k]=max(dp[j][k],dp[j-v[i]][k-w[i]]+val[i]);

cout

}

揹包問題 01揹包問題

n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...

揹包問題 01揹包

有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...

揹包問題(01揹包)

1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...