演算法筆記 揹包DP (0 1揹包)

2021-08-18 13:40:29 字數 2109 閱讀 2010

1.0/1揹包(參考例題:hloj416採藥)

二維解法:

我們設f[i][j]為前i個物品放進容量為j的揹包的最大價值

設體積為v[i],價值為w[i]:

我們可以列舉i(1到n)和j(1到n),不難得出狀態轉移方程

f[i][j]=max

可以知道,當第i件物品不取時,總價值為f[i-1][j]

取得話,總價值為前i-1件物品j-v[i]大小的最大值,j-v[i]是為了給第i件物品騰出空間來訪,加上第i件物品的價值,所以是f[i-1][j-v[i]]+w[i]

**如下:

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

for(int v=1;v<=t;v++)

一維解法:

可以知道,每一層i只被覆蓋一次就會浪費,會造成大量空間浪費,因此我們要進行一維陣列的優化。

假如我們直接把二維陣列去掉,會變成這個樣子:

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

for(int v=1;v<=t;v++)

因為我們把二維陣列去掉,原來是:前i件物品j個容量的揹包

而現在是:j容量的揹包放進的最大物品,前i件是被忽略的,因此這個方程的一部分:

f[v-c[i]]最優值並不是前i-1個物品的最優值,而是前i件物品的最優值,因為在當v(之前的)=v(當前的)-c[i]且i和當前列舉的i相同時,已經用過第i件物品了,所以是完全揹包,不是01揹包,所以我們可以選擇這麼做:將v逆序列舉,那麼我們就可以確保之前沒有被列舉過了。

最後附上01揹包(採藥)**:

#include

//f[i]表示容量為i的揹包所裝的物品的最大值

using

namespace std;

intmain

(),v[

10000

]={}

,f[10000

]={}

; cin>>v>>n;

//v表示揹包的總容量

for(

int i=

1;i<=n;i++)

cin>>v[i]>>w[i];

//v[i]表示每乙個物品的體積,w[i]為價值

for(

int i=

1;i<=n;i++)

//i列舉物品

for(

int j=v;j>=v[i];j--)

//j列舉體積,到v[i]既可以節約空間複雜度,也可以免去if

f[j]=

max(f[j],f[j-v[i]]+w[i]);

cout<}

2.01揹包的計數:以hloj417集合求和為例:

由題目可知,當n(n+1)%2==1時是無法分解為兩個集合的,因此直接判斷

當n*(n+1)為偶數的時候,我們就可以把它當成01揹包來做

如果是二維:設f[i][j]為前i個數總和為j的集合的方案數,把它想成01揹包,可以這麼得到方程:

如果i不要:那麼方案數是f[i-1][j]

如果i要且可以要:那麼方案數數f[i-1][j-i]

那麼f[i][j]的方案數總和就是f[i-1][j]+f[i-1][j-i].

那麼二維的寫法是這樣的:

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

for (int v=1;v<=ans;v++)

那麼其實一維陣列的寫法也是一樣的,自行理解把!

#include

//f[i]表示總和為i的集合方案數

using

namespace std;

intmain();

cin>>n;

sum=n*(n+1)/2

;if(sum%2==

1)sum/=2;

f[0]=1

;for

(int i=

1;i<=n;i++)

for(

int j=sum;j>=i;j--)

f[j]+=f[j-i];

cout

}

揹包DP(01揹包,多重揹包,完全揹包)

從前乙個轉態轉移過來,選還是不選 for int i 1 i n i else f i j f i 1 j 01揹包優化 滾動陣列 for int i 1 i n i for int j m j 1 j if weight i j f j max f j f j weight i value i 優...

ACM 程式設計競賽 DP 01揹包

輸入 n 4 w,v w 5 輸出 7 選擇0,1,3 暴力演算法 o 2 n include using namespace std const int maxn 100 int w maxn v maxn int n,w int rec int i,int j 從第i個商品開始挑選總重量小於j的...

揹包dp之01揹包

現在我們有n個配件,他們有不同的價值.但是我們揹包的容量是有限的,因為我們只有乙個一級包,所以我們最多可以裝v重量的東西.但是為了能更好的吃到雞 不存在的 我們要攜帶更有價值的配件,請問我們最多能拿多少價值的配件來當快遞員呢?輸入的第一行是t,表示有一共要打t場比賽.每組資料由三行組成.第一行包含兩...