揹包九講 之 01揹包及二維揹包

2021-10-03 10:01:37 字數 3729 閱讀 5774

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

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

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

輸出最大價值。

輸入格式

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

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

輸出格式

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

資料範圍

0經典的動態規劃,我們需要找到乙個合理的當前狀態以及相應的狀態轉移方程。已知資訊是物品數量n,揹包總體積v,以及各個物品的價值。

找合適的狀態

我們來嘗試拆分出子問題,物品價值是物品的屬性拆分它沒有價值,那我們就來拆分nv看看能不能分解出子問題,實際上是可以的,總問題是在物品數為n體積不超過v的情況下最大價值是多少。那我們就可以設想能否求出物品數為n-1體積不超過v-1的情況下最大價值是多少,這樣我們就找到了我們的當前狀態的表示方法,即用f[ i ][ j ]來表示前i個物品中在體積不超過j的情況下最大的價值是多少。

找狀態轉移方程

找到了當前狀態的表示,我們便很容易理清邊界情況,即當ij0f[ i ][ j ]的值便為0;接下來我們思考狀態轉移方程f[ i ][ j +1]能否通過f[ i ][ j ]得到呢?容量加一我們並不清楚之前的物品選擇狀態是什麼,所以我們無法由f[ i ][ j ]得到f[ i ][ j +1]。我們轉換思路考慮f[ i +1][ j ]能否通過f[ i ][ j ]得到,我們發現是可以的,因為f[ i +1][ j ]是比f[ i ][ j ]多乙個可選物品的的狀態。那麼這個物品就有兩種情況選與不選,如果我們不選這個物品那麼f[ i +1][ j ]的值就是f[ i ][ j ],如果選了那麼它的值就是選了這個物品的情況即f[ i ][ j -v[i]]+wi那它是否可知呢,答案是肯定的,因為我們外層迴圈我們的i,內層就得迴圈我們的j因此當我們求到f[ i ][ j ]f[ i ][ j -x] (xc++**:

#include

#include

using

namespace std;

int volume[

1003];

int value[

1003];

//根據資料範圍定義體積,價值表示第i個物品的體積,價值

int ans[

1003][

1003];

//根據資料範圍定義當前狀態ans[i][j]表示前i個物品在體積不超過j的前提下的最大價值

intmain()

for(i=

1;i1;i++

)//從第乙個物品開始遞推找前i個物品的各個狀態值

} cout<

[v]<

//輸出我們的答案即前n個物品體積不超過v的情況下的最大價值

return0;

}改進我們的**

觀察我們的**是否可以變得更簡潔些呢?我們發現當我們在求f[ i ][ j ]時,我們只用到了f[ i -1][ j ]f[ i-1 ][ j -v[i]]兩個值而我們最終只要能求出f[n][v]即可 。 所以我們可以不用二維陣列,我們可以用乙個一維陣列f[j]表示前i個物品情況下的狀態就行了,隨著我們i的增加不斷更新我們的陣列就行了。因為我們要更新這個陣列即要不斷覆蓋原來的值,此時體積就不可以從0v開始了因為因為在求f[j]可能會用到f[ j-v[i] ]所以不能從小到大覆蓋f[j]因為小的被覆蓋了大的就求不出了,所以我們應該從大到小覆蓋。

思路如下:

最終**:

#include
#include

using

namespace std;

int n,v;

int ans[

1003];

//根據資料範圍定義當前狀態ans[j]表示前i個物品在體積不超過j的前提下的最大價值

intmain()

} cout<

<

//最後的ans[n]即答案

return0;

}有 n 件物品和乙個容量是 v 的揹包,揹包能承受的最大重量是 m。每件物品只能用一次。體積是 vi,重量是 mi,價值是 wi。

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

輸出最大價值。

輸入格式

第一行兩個整數,n,v, m,用空格隔開,分別表示物品件數、揹包容積和揹包可承受的最大重量。

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

輸出格式

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

資料範圍

0思路分析:

在了經典的01揹包問題後,那麼這個二維揹包也就不難了,無非就是在加上一層迴圈,可以相當於我們對每一種體積都遍歷一遍體積或者可以對每一種體積都遍歷一遍重量。只要我們最外遍歷的是物品裡面的迴圈先後無所謂,因為他們都是物品的屬性而已,對於計算機來說它並不知道體積和重量的區別是啥。所以我們的套路就是先遍歷物品後依次遍歷物品屬性,在沒有優化我們的**前我們則需要乙個三維陣列來儲存答案了。現在我們可以用優化的方法,用乙個二維陣列滾動儲存答案。

c++**:

#include
#include

using

namespace std;

intmain()

}}cout<

[m]<

//輸出答案

return0;

}

揹包九講之 01揹包

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

二維費用揹包問題(揹包九講)

前言 對於一些揹包問題,重點還是在於如何找出 揹包容量 和 各種代價 以及價值,如此問題便迎刃而解了。下午 打籃球居然下冰雹了,悲催了。問題 二維費用的揹包問題是指 對於每件物品,具有兩種不同的費用 選擇這件物品必須同時付出這兩種代價 對於每種代價都有 乙個可付出的最大值 揹包容量 問怎樣選擇物品可...

揹包九講之二維成本揹包

多重揹包的理解請建立在01揹包與完全揹包的基礎上,在了解01揹包與完全揹包後,多重揹包即可不攻自破。01揹包 完全揹包 多重揹包 混合揹包 二維成本即一種物品需要支付兩種成本,前四講中,所有物品僅有乙個重量成本,放在容量為v的揹包當中,而在二維成本揹包中,則多了乙個約束。具體描述 有n種物品,其中第...