DP 揹包九講之01揹包

2021-10-07 03:16:20 字數 1749 閱讀 5934

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。

第 i 件物品的體積是 vi,價值是 wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。

輸出最大價值。

輸入格式

第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。

接下來有 n 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。

輸出格式

輸出乙個整數,表示最大價值。

資料範圍

001揹包是動態規劃中揹包問題很典型的乙個題,大意為有一些物品和乙個有一定體積的揹包,每個物品都有自己的價值,詢問揹包內物品的最大價值是多少?

列舉每乙個物品,通過對每乙個物品的取捨來推導狀態轉移方程:

我們用3個陣列來表示狀態,w[n]來表示每乙個物品的價值,v[n]表示每個物品的體積,dp【n】【n】,dp【i,j】表示,當前最多拿 i 個物品,體積小於等於 j 時的最大價值是多少。

關於第 i 個物品的取捨問題:

1. 第 i 個物品不要,則當前狀態和 i-1 的狀態相同,則dp[i][j]=dp[i-1][j]。

2. 第 i 個物品要,則當前狀態等於j-v[i]體積下的最大價值+w[i],所以在這種狀態下,dp[i][j]=dp[i-1][j-v[i]]+w[i]。

目的是求最大價值,因此狀態轉移方程:

dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+w[i])

普通01揹包**:

#include

#include

#include

using

namespace std;

const

int n =

1e3+50;

int w[n]

,v[n]

,dp[n]

[n];

intmain()

cout<[m]

}

我們發現當前 i 個物品只和 i-1 個物品的狀態有關,所以我們可以把dp陣列從二維優化到一維,dp[n],dp[i]表示在體積 i 的範圍之內的最大價值。我們可以讓二維陣列原地滾動。

一維狀態轉移方程:dp[j]=max(dp[j],dp[j-v[i]]+w[i])

先貼**:

#include

#include

#include

using

namespace std;

const

int n =

1e3+50;

int w[n]

,v[n]

,dp[n]

;int

main()

觀察**發現,和二維不一樣的是,一維的內迴圈是從m->v[i],為什麼呢,因為要實現原地滾動,就要借助上一次修改的值(i-1),但是如果從前往後遍歷的話,會造成一種什麼情況,因為是一維陣列,所以上一次修改的值在這一次開始操作的時候已經被覆蓋了,導致後面的 j 在做狀態轉移方程時,使用的是當前行的值而不是 i-1 行,導致結果不准,所以我們從後往前遍歷,先改後面再改前面,保證每乙個j 都使用的 i - 1 行的值,再結合狀態轉移方程,最後dp[m]即為要求的值,意為在m體積範圍內可以帶走的最大價值。

DP 揹包九講之01揹包

有n件物品和乙個容量為v 的揹包。放入第i件物品耗費的空間是ci,得到 的價值是wi。求解將哪些物品裝入揹包可使價值總和最大。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不 放。用子問題定義狀態 即f i,v 表示前i件物品恰放入乙個容量為v的揹包可以 獲得的最大價值。則其狀態轉移方...

DP 揹包九講之01揹包

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,每行兩個整數 ...

揹包九講之 01揹包

01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...