我有不同类别的物品。每个项目都有value
和weight
。
例如:
ClassA: [A1, A2, A3]
ClassB: [B1, B2, B3]
ClassC: [C1, C2, C3]
我应该如何修改经典0-1背包问题,以便算法优化解决方案最大化整体价值,考虑课堂上的所有项目,但允许从一个类别中选择最多一个项目?
package knapsack;
import java.util.ArrayList;
import java.util.List;
public class Knapsack {
private int totalNumberOfItems;
private int maxmimumKnapsackCapacityUnits;
private double[][] optimum;
private boolean[][] solution;
private double [] value;
private int [] weight;
public Knapsack(int knapsackCapacityUnits, List<KnapsackItem> items){
this.totalNumberOfItems = items.size();
this.maxmimumKnapsackCapacityUnits = knapsackCapacityUnits;
this.optimum = new double[items.size() + 1][knapsackCapacityUnits + 1];
this.solution = new boolean[items.size() + 1][knapsackCapacityUnits + 1];
this.value = new double[items.size() + 1];
this.weight = new int[items.size() + 1];
int index=1;
for(KnapsackItem item : items){
value[index] = item.value;
weight[index] = item.weight;
index++;
}
}
public List<KnapsackItem> optimize(){
for(int currentItem = 1; currentItem <= totalNumberOfItems; currentItem++){
for(int currentWeightUnit = 1; currentWeightUnit <= maxmimumKnapsackCapacityUnits; currentWeightUnit++){
double option1 = optimum[currentItem - 1][currentWeightUnit];
double option2 = Integer.MIN_VALUE;
if(weight[currentItem] <= currentWeightUnit){
option2 = value[currentItem] + optimum[currentItem-1][currentWeightUnit - weight[currentItem]];
}
optimum[currentItem][currentWeightUnit] = Math.max(option1, option2);
solution[currentItem][currentWeightUnit] = (option2 > option1);
}
}
boolean take [] = new boolean[totalNumberOfItems + 1];
for(int currentItem = totalNumberOfItems,
currentWeightUnit = maxmimumKnapsackCapacityUnits;
currentItem > 0; currentItem --){
if(solution[currentItem][currentWeightUnit]){
take[currentItem] = true;
currentWeightUnit = currentWeightUnit - weight[currentItem];
}
else{
take[currentItem] = false;
}
}
List<KnapsackItem> items = new ArrayList<KnapsackItem>();
for(int i = 0; i < take.length; i++){
KnapsackItem newItem = new KnapsackItem();
newItem.value = value[i];
newItem.weight = weight[i];
newItem.isTaken = take[i];
items.add(newItem);
}
return items;
}
}
谢谢!
答案 0 :(得分:2)
经典算法如下:
for i in items:
for w in possible total weights (downwards):
if w is achievable with maximum value v:
(w + weight[i]) is also achievable with at least value (v + value[i])
这里的方法略有不同:
for c in classes:
for w in possible total weights (downwards):
if w is achievable with maximum value v:
for i in items of class c:
(w + weight[i]) is also achievable with at least value (v + value[i])
使用您的代码,更改将如下所示:
也许您会想为每个班级单独列出一个项目。与当前所做的一致,我希望value
和weight
成为列表列表,以及一些名为numberOfClasses
和numberOfClassItems
的变量和数组来监控新名单的长度。
例如,假设两个1类项目是(w = 2,v = 3)和(w = 3,v = 5),三个2类项目是(w = 1,v = 1),(w = 4, v = 1)和(w = 1,v = 4)。然后我们将:
totalNumberOfItems = 5
,
numberOfClasses = 2
,
numberOfClassItems = [2, 3]
,
value = [[3, 5], [1, 1, 4]]
和
weight = [[2, 3], [1, 4, 1]]
。
那就是你从0
索引。从1
开始编制索引会在每个列表的开头留下未使用的零或空列表。
for (currentItem)
循环将成为for (currentClass)
循环。数组optimum
和solution
将被currentClass
而不是currentItem
编入索引。
实际上,值option2
将被计算为几个选项中的最佳选项,每个类项目一个:
double option2 = Integer.MIN_VALUE;
for (currentItem = 1; currentItem <= numberOfClassItems[currentClass];
currentItem++){
if(weight[currentClass][currentItem] <= currentWeightUnit){
option2 = Math.max (option2, value[currentClass][currentItem] +
optimum[currentClass - 1][currentWeightUnit -
weight[currentClass][currentItem]]);
}
}
也许solution
数组现在应该包含int
而不是boolean
:我们采用的这个类的项目数,或者一些标记值({{1} }或0
)如果我们选择-1
并且不使用此课程的任何项目。
答案 1 :(得分:0)
解决此问题的方法是将类A,B,C
视为项目本身,然后继续在单个类中进行选择以从中选择最佳项目。
number of items = number of classes = N
Knapsack capacity = W
Let item[i][k] be kth item of ith class.
简单的DP解决问题,简单修改背包解决方案: -
int DP[n][W+1]={0};
//base condition for item = 0
for(int i=0;i<=W;i++) {
for(int j=0;j<item[0].size();j++) {
if(i>=item[0][j].weight) {
DP[0][i] = max(DP[0][i],item[0][j].value);
}
}
}
//Actual DP
for(int k=0;k<=W;k++) {
for(int i=0;i<n;i++) {
for(int j=0;j<item[i].size();j++) {
if(k>=item[i][j].weight) {
DP[i][k] = max(DP[i][k],DP[i-1][k-item[i][j].weight]+item[i][j].value);
}
}
DP[i][k] = max(DP[i][k],DP[i-1][k]);
}
}
print("max value : ",DP[n-1][W]);