问题描述
多背包问题(MultiplePack):有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
-
是0-1背包问题的延伸,与0-1背包问题的不同点在于把一个背包换成了多个背包,大致意思是有一堆物品放入n个背包中,要使其价值最大,应该怎么放。
-
这个问题进一步延伸是不考虑n个背包价值最大化,而是要使得n各背包的价值尽可能相同。
详见:(http://www.wutianqi.com/?p=539)
解决方案
因为对于第i种物品有n[i]+1种策略:取0件,取1件……取n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程:
f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}
将其转换为01背包,普通的转换对于数量较多时,则可能会超时,可以转换成二进制,对于普通的,就是多了一个中间的循环,把j=0~bag[i],表示把第i中背包从取0件枚举到取bag[i]件。
核心代码
public static void multiplePack(int cost,int weight,int amount) {
if(cost * amount >= 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);
}
public static void completePack(int cost,int weight) {
for(int j = cost; j <= V; j++) {
f[j] = Math.max(f[j], f[j-cost] + weight);
}
}
public static void zeroOnePack(int cost,int weight) {
for(int j = V; j >= cost; j--) {
f[j] = Math.max(f[j], f[j-cost] + weight);
}
}
全部代码在:https://gitee.com/KSRsusu/arithmetic/tree/master/src/multiKnapsack