揹包問題模板

2021-08-17 20:49:45 字數 1687 閱讀 2184

01揹包在時間複雜度上都是n(n*v),在這個基礎之上已經不能再進行優化了,在空間複雜度上,我們首先看一下複雜度為o(n*v)的程式

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

for(int j = 0;j <= w;j ++)

但是我們還可以將空間複雜度壓縮為o(v),我們會發現這裡每次更新第i層都只是看第i-1層,其他層的資訊都不會參與第i層的計算,這樣我們就會立馬想到滑動陣列,我們每次都是用到第i-1行,j位置之前的資料,那麼我們就可以直接使用乙個陣列dp[v],然後進行從後向前的更新(因為如果先更新前面的話,更新後面會產生影響),這樣我們的空間複雜度就會降為o(v)。

那麼這時的狀態轉移方程為 dp[ j ] = max( dp[ j ] ,dp[ j - w[ i ] ] + v[ i ] )

dp[j] = max(dp[j], dp[j-w[i]]+v[i]);
for(int i = 1;i <= n;i++)

for(int j = w;j >= w[i];j --)

完全揹包問題和01揹包不同的地方只有:完全揹包中所有的物品都是無限個

這樣我們上面在01揹包中我們第二層迴圈中j是從w ~ w[i],這樣就保證了每一次更新都是從上一層開始更新的,這一層更新中不會產生任何影響。

那麼我們就可以在完全揹包中使用這種思路,第二層迴圈中從w[i] ~ w就是從已經放入的物品i的狀態下轉移而來,那麼我們的狀態轉移方程就可以表示為:

dp[ j ] = max( dp[ j ] , dp[ j - w[ i ]] + v[ i ] )

void solve()

完全揹包表示在每種物品都有數量限制的情況下,怎麼拿能拿到最大的價值。

我們這裡思路就是把多重揹包轉換為01揹包來計算,這裡是看了dd大牛的《揹包九講》的模板,我們把一種物品分成相應的幾部分,然後每部分的這一部分的價值和重量就是這個係數乘以乙個的價值和重量,具體的分開的方式是分成:1,2,2^2,2^3......2^(k-1),mi - 2^k +1

mi表示第i種物品的數量,k滿足最後乙個式子大於0的最大整數。

那麼它的狀態轉移方程和01揹包的狀態轉移方程就相同了。

我們先看乙個複雜度為o(v σm

i )的例子:poj1276

#include #include #include using namespace std;

const int maxm = 101000;

int n;

int dp[maxm];

int main()

if(cash == 0 || n == 0)

int max = 0;

dp[0] = 1;

for(int i = 0;i < n;i ++) //迴圈所有的金錢種類

for(int j=max;j >= 0;j --) //轉換為01揹包問題,所以這裡要從後向前更新陣列,但是這裡的max也是不斷的更新的,並且max <= cash}}

printf("%d\n",max);

}}

我們運用開始的優化,可以將原問題複雜度轉換為o(v

σlogmi):hdu1059

實在是優化不來.......

揹包問題模板

特點 每種物品只有一件 子問題定義狀態 bag i v 前i件物品放到乙個容量為v的揹包中可以獲得最大價值 轉移狀態方程 bag i v max bag i 1 v bag i 1 v weight i value i 模板 include include using namespace std i...

模板 揹包問題

include include define max a,b a b a b using namespace std const int n 1005 int n,v,v n w n int dp n voidf intmain f printf d n dp v return0 include i...

揹包問題模板

有n種物品和乙個容量為v的揹包。第 i 件物品的體積是 c i 價值是 w i 由於每種物品有且僅有一件,因此只能選擇放或不放,我們稱之為 01 揹包問題。現在你需要選出若干件物品,在它們的重量之和不超過 v 的情況下,使總價值盡可能達到最大。for int i 1 i n i else 優化空間複...