用二進位制優化多重揹包問題

2021-10-24 07:16:21 字數 1930 閱讀 8619

多重揹包是這樣的乙個問題:

有n種物品,第i種物品的體積為ci,價值是wi,但是每種物品的數量都是有限的,為ni。現在有容量為v的揹包,請你放入若干物品,使獲得的價值盡量大。

樸素演算法:

把n種物品逐個拆分,得到σni個物品,則原問題可轉化為01揹包求解。這樣做的時間複雜度為o(v×σn)。

或者是在列舉種類的過程中列舉個數k,這樣做可以優化空間複雜度,但時間複雜度也是o(v×σn)。

優化:

我們可以考慮二進位制的思想,將第i種物品拆分成若干件物品,可以有(ci,wi),(ci×2,wi×2),(ci×4,wi×4),等等,每個物品有乙個係數,1, 2, 4, 8… 2k-1, n-2k+1

其中,k是滿足n-2k+1>0的最大整數。

比如可以用1,2,4,8,5(20-1-2-4-8=5)這5個數進行組合並相加,來得到20以內的任何數。

這樣一來,從n件物品就拆分成了至多logn件物品,再轉化為01揹包問題求解,複雜度降低到o(vσlogn)。

思考:

實際上還是運用了倍增的思想。

與之前的倍增略有不同的是,這次不再是將給定的k運用二進位制編碼進行組合(對於給定的k,確對應乙個二進位制編碼,一定可以用2p將其組合出來)。

而是將k以二進位制的形式進行拆分,再對拆分後的數進行組合。(保證1~k中的每個數都能由這幾個數最多使用一次組合出來)。

例題:

description

byteotian bit bank (bbb) 擁有一套先進的貨幣系統,這個系統一共有n種面值的硬幣,面值分別為b1, b2,…, bn. 但是每種硬幣有數量限制,現在我們想要湊出面值k求最少要用多少個硬幣.

input

第一行乙個數 n, 1 <= n <= 200.

接下來一行 n 個整數b1, b2,..., bn, 1 <= b1 < b2 < ... < b n <= 20 000,

第三行 n 個整數c1, c2,..., cn, 1 <= ci <= 20 000, 表示每種硬幣的個數.

最後一行乙個數k – 表示要湊的面值數量, 1 <= k <= 20 000.

output

第一行乙個數表示最少需要付的硬幣數

裸的多重揹包問題,狀態f[i][j]表示用i種硬幣湊出j元最少需要多少個硬幣。

狀態轉移方程:f[i][j]=min(f[i-1][j-v[i]]+1,f[i-1][j])。

code:

#include

#include

const

int maxn=

211;

int n;

int b[maxn]

,w[maxn*maxn]

,v[maxn*maxn]

,f[20011];

intmain()

w[++cnt]

=c-(t-1)

; v[cnt]

=b[i]

*w[cnt];}

int k;

scanf

("%d"

,&k)

;for

(int i=

1;i<=k;i++

) f[i]

=200015

; f[0]

=0;for

(int i=

1;i<=cnt;i++

)for

(int j=k;j>=v[i]

;j--

)printf

("%d"

,f[k]);

return0;

}

多重揹包二進位制優化

多重揹包二進位制優化 將價值數量相同的物品分成1,2,4,8.因為100以內任何數都可以由幾個2的n次方數組成。所以,有遍歷沒乙個數變為遍歷每乙個2的n次方數。例題 有n種物品,每種物品的數量為c1,c2.cn。從中任選若干件放在容量為w的揹包裡,每種物品的體積為w1,w2.wn wi為整數 與之相...

多重揹包(二進位制優化)

馬上就要輕院校賽了,沒時間了,下面是網上找的多重揹包,感覺很好 void zeroonepack int cost,int weight,int n void completepack int cost,int weight,int n void multipack int c,int w,int ...

多重揹包二進位制優化

時間長不寫 感覺變菜了。整體優化思路和快速冪很相近 如果第i個物品有num i 個,花費是 c i 價值是 v i 那麼我們可以把它拆分成數個物品。比如某個物品數量是14 花費是cost 價值是value 1 2 4 7 就可以把14個相同物品看成 4 個不同的物品,物品 數量花費 價值第乙個 11...