問題描述spa
有N種物品和一個容量爲V的揹包,第i中物品最多有n[i]件可用。每一件的費用是c[i],價值是w[i]。
求將哪些物品放入揹包可使得這些物品的費用總和不超過揹包的容量,同時價值總和最大。
問題分析
這個問題的狀態轉移方程和徹底揹包的十分的類似,惟一改變的就是第i種物品只有1+n[i]種策略可選擇。
分別是0,1,2,....n[i]。
dp[i,v]=max{ dp[i-1,v],dp[i-1,v-k*c[i]]+k*w[i] }
這《揹包九講》中將這個問題轉換。基本思想就是將第i種分紅若干份,使得第i中物品可取的
每一種策略即取0,1,2,3.....n[i] 均可以等價的取若干份來代替。
因而如今的問題即是第i中物品應該怎樣的份才能達到上述的目的呢??
定理:一個正整數n能夠被分解成1,2,4,....,2k-1 n-2k-1+1 (其中k是知足n-2k-1+1>0的最大整數)的形式,
且1~n內的全部整數均可以惟一表示成1,2,4,....,2k-1 n-2k-1+1中某幾個數的和的形式。
所以按照這個定理,咱們把第i中物品的個數n[i]分紅
1,2,4,....,
2
k-1
n-2
k-1
+1的形式。
也就是把第i種物品細分了,每一分的個數爲
1,2,4,....,
2
k-1
n-2
k-1
+1。 因而咱們將問題邊轉換了這些細分後物品的01揹包問題。
因而這個代碼能夠表示爲:
produce MultiplePack(
int cost,
int weight,
int amount)
if cost
*amout
>
=V
CompletePack(cost,weight)
//這一份物品不能所有放入取了之後有剩餘,那麼對於揹包這個物品有無限個
return
int k
=
1
while(k
<
=amount)
ZeroOnePack(k
*cost,k
*weight)
amount
-=k
k
*=
2
ZeroOnePack(amount
*cost,amount
*weight)
這裏須要01揹包和徹底揹包做爲基礎。