詳解01揹包

2021-10-17 03:43:13 字數 3504 閱讀 3198

假設有乙個小偷,他帶了乙個揹包想偷東西,這個揹包的容量capacity = 8。他可以偷的物品一共有四個,每個物品都有自己的價值和重量,每個物品都可以選擇放或者不放(放就得到1個物品,不放就得到0個物品,因此得名0/1揹包)。那麼,在揹包可承受的最大重量為8的前提下,如何選取要偷的物品,使得所偷物品的總價值最大?即求max(總價值)

揹包的基本模型:

揹包是最典型、最基本的dp問題。給你乙個容量為v的揹包和若干種物品,在一定的限制條件下(每種物品都占用一定容量),問最多能放進多少價值的物品?即求價值的最優解

下表是每個物品的價值和重量:

首先引入一下pack( i , j )的意思:

pack( i , j )表示考慮從第1件到第 i 件物品,在揹包承受能力為 j 的情況下,能拿到物品的最大值。

如:pack(4,8)表示從第一件物品到第四件物品全考慮進來,在揹包容量為8的情況下能拿到的最大價值。

pack(3,8)表示從第一件物品到第三件物品考慮進來,在揹包容量為8的情況下能拿到的最大價值。即不考慮第四件物品的情況下的max(總價值)

pack(2,7)表示只考慮前兩件物品,且揹包容量為7的情況下能拿到的最大價值。

pack(1,0)表示只考慮第一件物品,且揹包容量為0的情況下能拿到的最大價值。很容易看出pack(1,0) = 0。因為揹包的可承受重量為0,即不能放下任何乙個物品(買了個假包哈哈)

pack(0,0)表示不考慮任何一件物品且揹包的容量也為0(可以理解為小偷就來溜個彎不打算偷東西或者他發現自己買了個假包所以放棄了偷東西。嗯?會不會是先來打探敵情?)

pack(1,1)表示只考慮第一件物品,且揹包容量為1的情況下能拿到的最大價值。而第一件物品的重量為2,故易得pack(1,1 )= 0。

pack(1,2)表示只考慮第一件物品,且揹包容量為2的情況下能拿到的最大價值。這種情況表示可以拿走第一件物品,故pack(1,2)為第一件物品的價值,即pack(1,2) = 1。

當然,我們的目的是求出pack(4,8)的值。而要求出pack(4,8),就要先求出pack(0,0),pack(0,1),pack(0,2)… …pack(1,0),pack(1,1),pack(1,2)… … 最終根據簡單的情況得出複雜的結果pack(4,8),這也是動態規劃的核心思想

(重要!!!)01揹包狀態轉移方程:

下面對pack(i-1,j-w[i])+ price[i]做乙個更詳細的解釋:

假設初始要從第一件物品考慮到第四件物品,且揹包的容量為7,即pack(4,7)。現在選擇第四件物品進入揹包,那麼之後就要繼續考慮前三件物品,用 i - 1 來表示。且第四件物品進入揹包後,揹包的總容量需要減去第四件物品的重量,用 j-w[i] 來表示,即7 - weight[ 4 ] = 7 - 5 = 2。最後,再加上第四件物品的價值。

按此方法依次填寫下面**,最終可以求出pack(4,8)

對於**第一行,由於 i 恆等於0,表示不考慮物品,故第一行恆等於0。

對於**第一列,由於 j 恆等於0,表示揹包的容量為0,故第一列也恆等於0。

部落格上面已經寫到pack(1,1) = 0 , pack(1,2) = 1

故初步填寫**如下:

對於pack(1,3),可以使用公式計算:

由於此時揹包的容量為3,第一件物品的重量為2,可以放下第一件物品,所以

pack(1,3)=

= max

= max

= max

= max

= max

= 1同理可填完**:得到pack(4,8) = 8

01揹包**實現如下:

#include

#include

#include

#include

using

namespace std;

int w[5]

=;//重量陣列,表示四件物品的重量

int v[5]

=;//價值陣列,表示四件物品的價值

int f[5]

[9]=

;//二維陣列

intmain()

}//輸出二維陣列

模板題原題鏈結

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

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

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

輸出最大價值。

輸入格式

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

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

輸出格式

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

資料範圍

0ac**:

#include

#include

#include

#include

using

namespace std;

const

int n =

1010

;int f[n]

[n];

int w[n]

;//體積陣列

int v[n]

;//價值陣列

intmain()

}printf

("%d"

,f[n]

[m])

;return0;

}

0 1揹包(詳解)

0 1揹包問題 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。這個問題的特點是 每種物品只有一件,可以選擇放或者不放。演算法基本思想 利用動態規劃思想 子問題為 f i v 表示前i件物品恰放入乙個...

01揹包詳解

看了2天的01揹包,感覺現在真的是懂了,記錄一下,這樣才能記得更加深刻,其實早就接觸過01揹包,當時一知半解的,今天看了書本和別人的部落格,真的很有用 1 描述一下01揹包問題 有n個重量和價值分別為wi,vi,的物品,從這些物品中挑選出總重量不超過w的物品,求所有的挑選方案中價值總和的最大值。這裡...

01揹包,完全揹包,多重揹包詳解

揹包之01揹包 完全揹包 多重揹包詳解 ps 大家覺得寫得還過得去,就幫我把部落格頂一下,謝謝。首先說下動態規劃,動態規劃這東西就和遞迴一樣,只能找區域性關係,若想全部列出來,是很難的,比如漢諾塔。你可以說先把除最後一層的其他所有層都移動到2,再把最後一層移動到3,最後再把其餘的從2移動到3,這是乙...