问题描述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背包和彻底背包做为基础。