leetcode補充學習之DP 01揹包問題

2021-10-05 09:18:24 字數 3264 閱讀 1985

寫在前面:

最近越來越忙了,主要原因是真的太菜了,做個題需要好久,這兩天題涉及還蠻複雜,昨天是dfs與bfs搜尋,我打算等有時間複習一下再一併寫。

結果今天居然來了個dp,好傢伙 又不會,只能一步一步來了。

今天的題是完全揹包問題,後面再說,這裡只記錄01揹包問題。主要學習狀態轉移函式等。

廢話少說 直接放題:

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

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

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

輸出最大價值。

輸入格式

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

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

輸出格式

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

資料範圍

0樣例輸入

451

2243445

樣例輸出

8
其實這道題的關鍵我已經標黑了,就是每個物品只能拿乙個,不能重複拿。

主要關鍵就是這個f[i][j],它代表著只看前i個物品 總體積是j的情況下 總最大價值

//01揹包問題-二維解法 

//f[i][j] 表示只看前i個物品 總體積是j的情況下 總最大價值

#include

using namespace std;

int arrw[

1010];

int arrv[

1010];

int f

[1010][

1010];

//狀態轉移

int main()

int res=0;

for(int i =

0;i<=

v;i++

) res=

max(res,f[

n][i])

; cout<

return0;

}

這裡直接貼入樣例輸入,列印f[i][j]看看是什麼東西,簡單明瞭。

第0行 第0列 全是0代表我們沒有空間或者沒有物品的情況下什麼都沒有自然就是0

當有1個空間 1個物品時 就是2 代表我們拿了第乙個物品

當有2個空間 2個物品時 就是4 代表拿的第二個物品

//f[i][j] 表示只看前i個物品 總體積是j的情況下 總最大價值

f[i]

[j]=

f[i-1]

[j];

//不拿第i個物品

f[i]

[j]=

max(

f[i]

[j],

f[i-1]

[j-arrv[i]

]+arrw[i]);

//拿

再看這**就明白了 如果要拿第i個物品

就應該滿足在i之前的空間足夠放i物品情況下的最大價值來拿

例如目前為3空間 我可以拿兩個物品:第二個物品它是2空間,4價值

那麼就要找只有第一種物品的情況下空間為3-2=1此時的最大價值也就是2.

所以拿了之後的總價值是4+2=2。

不拿總價值就是2。

其實理解這個並不難,實際卡住我的是所謂的二維陣列優化為一維 優化空間複雜度。

也就是下面的**

//01揹包問題-一維解法 

#include

using namespace std;

int arrw[

1010];

int arrv[

1010];

int f

[1010];

//f[i]表示體積為i的情況下最大價值

int main()

int res=0;

for(int i =

0;i<=

v;i++

) res=

max(res,

f[i]);

cout<

return0;

}

難點就在於下面這裡

為什麼第二個迴圈是逆著算的

其實可以這麼來解釋:如果採用順序迴圈

當計算f[j]的時候右邊需要計算f[j-arrv[i]]

例如:當我們算f[5]時第一次取物品時 它就需要計算 f[4],但f[4]在上乙個迴圈已經計算了

它有可能已經拿了第i個物品了

//逆序

for(int i =

1;i<=

n;i++

)for

(int j=

v;j>=arrv[i]

;j--)f

[j]=

max(

f[j],f

[j-arrv[i]

]+arrw[i]);

//順序

for(int i =

1;i<=

n;i++

)for

(int j=

1;j<=

v;j++

)

這裡同樣輸出兩種情況的過程看一下就知道了

首先是逆序的輸出

然後是順序

對於這個樣例輸入

當可拿物品只有1個 空間為2,3,4,5的時候 都重複的拿了第乙個物品

就是因為我們計算f[2]的時候f[1]它已經拿了第1個物品了,此時再取1顯然已經非法了。

而逆著算就正好避免了這一問題。

4

5//左邊空間 右邊價值12

2434

45

好了,本篇文章就到這裡,下次繼續 完全揹包 問題

js學習之原型 補充)

建立乙個建構函式 function myclss 新增乙個name屬性 myclass.prototype.name 原型 var mc new myclass console.log mc.name 原型 使用in檢查物件中是否含有某個屬性,如果物件沒有,但原型中有的話,也會返回true cons...

redis學習 補充學習

redis是乙個開源的記憶體中的資料結構儲存系統,它可以用作 資料庫 快取和訊息中介軟體。是乙個完全開源免費的key value記憶體資料庫通常被認為是乙個資料結構伺服器,主要是因為其有著豐富的資料結構strings map list sets sorted sets1 完全基於記憶體,絕大部分請求...

c 學習補充

1.在類的定義中,一般資料成員設為私有,函式成員設為共有。2.私有成員只能在類內使用,不能再類外,即宣告乙個物件後,不能用std.mame這種形式去呼叫私有成員,只能呼叫共有成員。3.我們知道建構函式是用來初始化資料成員的,但是有比他更好的,那就是初始化列表,他更快,更專業。4.類的定義就是封裝 5...