揹包問題總結

2021-10-05 15:25:29 字數 3465 閱讀 2154

題意:有n個物品,揹包總容量為v,第 i 個物品的體積為v

iv_i

vi​,價值為w

iw_i

wi​,求裝入揹包的最大價值

思路

狀態表示f[i][j]= 集合:所有只考慮前i種物品且總體積不超過j的方案的集合\\ 屬性:取其中價值最大的方案 \end}\\ 狀態計算:找最後乙個不同點,對第 i 個物品取或者不取 \end

⎩⎪⎨⎪⎧​

狀態表示

f[i]

[j]=

printf

("%d\n"

,dp[n]

[m])

;return0;

}空間優化

#include 

#include

using namespace std;

const

int maxn=

1010

;int n,m,w[maxn]

,v[maxn]

,f[maxn]

;int

main()

思路

狀態表示f[i][j]= 集合:所有只考慮前i種物品且總體積不超過j的方案的集合\\ 屬性:取其中價值最大的方案 \end}\\ 狀態計算:找最後乙個不同點,對第 i 個物品取0個,1個,2個 \end

⎩⎪⎨⎪⎧​

狀態表示

f[i]

[j]=

} cout<[m]<<

"\n"

;return0;

}優化空間

#include .h>

using namespace std;

const

int maxn=

1010

;int n,m,w[maxn]

,v[maxn]

,f[maxn]

;int

main()

思路

狀態表示f[i][j]= 集合:所有只考慮前i種物品且總體積不超過j的方案的集合\\ 屬性:取其中價值最大的方案 \end}\\ 狀態計算:找最後乙個不同點,對第 i 個物品有 [0,s]種取法 \end

⎩⎪⎨⎪⎧​

狀態表示

f[i]

[j]=

思路:狀態設定:f[i

][j]

f[i][j]

f[i][j

]表示所有前i個物品總體積不超過 j 的方案的集合,然後取乙個價值最大的方案

採用了二進位制優化,因為有 s

ss 件物品,用二進位制可以表示 s

ss 中的任意乙個數

#include .h>

using namespace std;

int n,m,w,v,s;

int f[

2010];

vectorint,

int>

> vec;

intmain()

);}if

(s>0)

vec.

push_back()

;}for(auto i : vec)

for(

int j=m;j>=i.first;

--j)

f[j]

=max

(f[j]

,f[j-i.first]

+i.second)

;printf

("%d\n"

,f[m]);

return0;

}

題意:有n類物品,揹包總容量為v,第i類物品,有s

is_i

si​件體積為v

iv_i

vi​,價值為w

iw_i

wi​,求裝入揹包的最大價值

思路:狀態設定還是f[i

][j]

f[i][j]

f[i][j

]表示前i個物品總體積不超過 j 的最大價值

分析:這裡n範圍在1000,v的範圍在20000,s的範圍在20000以內。如果還是採用二進位制優化的話。時間複雜度是:1000×l

og2(

20000)×

20000

1000\times log_2(20000)\times 20000

1000×l

og2​

(200

00)×

2000

0,大約是3e8,會超時。所以可以採用單調佇列優化的方法

優化思路:我們發現每乙個f[i

][j]

f[i][j]

f[i][j

]其實都是從f[i

−1][

j−w]

、f[i

−1][

j−2∗

w]、…

、f[i

−1][

j−s∗

w]

f[i-1][j-w]、f[i-1][j-2*w]、\dots、f[i-1][j-s*w]

f[i−1]

[j−w

]、f[

i−1]

[j−2

∗w]、

…、f[

i−1]

[j−s

∗w]轉移過來的,因此我們可以根據餘數 r 分組,每一組是:r、r

+w、r

+2w、

…r、r+w、r+2w、\dots

r、r+w、

r+2w

、…,維護乙個最大值單調佇列,每次先判斷入隊,然後縮減區間,最後更新 f[j

]f[j]

f[j]

#include .h>

#define ll long

long

using namespace std;

const

int maxn=

2e4+

5,maxm=

1e5+5;

const

int mod=

1e9+

7,inf=

0x7f7f7f7f

;int n,m;

int w[maxn]

,v[maxn]

,s[maxn]

;int q[maxn]

,h,t;

int f[maxn]

,g[maxn]

;int

main()

}}printf

("%d\n"

,f[m]);

return0;

}

揹包問題 01揹包總結

寫這篇部落格的原因是因為自己初學揹包的時候覺得好玄學。只是知道怎麼寫,但是具體是為什麼覺得很玄妙。在此其實希望和我一樣的小白萌新早點明白其中的原理,其實原理很簡單,只要懂了這個圖,我想01揹包就不成問題了。首先要明確這張表是至底向上,從左到右生成的。關於01揹包的題目暫時整理了一點。1.簡單01揹包...

揹包問題總結

標籤 acm dp 揹包 n 物品,乙個揹包,每個物品價值wi 體積vi 揹包容量 c 求最大價值 對於物品 i可選可不選 fi j fi 1 j vi j 0 fi j max c j vi 給定 n 種物品和乙個揹包。第 i種物品的價值是 wi 其體積為vi 揹包的容量為 c 同一種物品的數量無...

揹包問題總結

揹包問題主要是分為三種 0 1揹包,完全揹包,多重揹包 1 0 1揹包 定義 何謂0 1揹包,可以這樣想,那裡有一堆值錢的東西,每一樣東西只有一件,他們的價值和體積都不一樣,現在要你從這n件裡面挑選一些放到乙個容量一定的揹包裡面,使得你的揹包裡的東西總價值最大。對於這些東西的每一件,你可以選擇放進你...