Algorithm 改进的背包算法
我有不同种类的物品。每个项目都有Algorithm 改进的背包算法,algorithm,knapsack-problem,Algorithm,Knapsack Problem,我有不同种类的物品。每个项目都有值和重量 例如: 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
值
和重量
例如:
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;
}
}
包裹背包;
导入java.util.ArrayList;
导入java.util.List;
公务舱背包{
私人int totalNumberOfItems;
私有int最大背包容量;
私人双[]最优;
私有布尔[][]解决方案;
私人双[]值;
私有int[]权重;
公共背包(int背包,列表项){
this.totalNumberOfItems=items.size();
this.maxmimumKnapsackCapacityInits=背包容量Inits;
this.optimum=新的双精度[items.size()+1][背包容量yunits+1];
this.solution=new boolean[items.size()+1][knapsackCapacityUnits+1];
this.value=新的双精度[items.size()+1];
this.weight=新整数[items.size()+1];
int指数=1;
用于(背包项目:项目){
值[索引]=项值;
重量[指数]=项目重量;
索引++;
}
}
公共列表优化(){
对于(int currentItem=1;currentItem,经典算法如下:
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
进行索引将在每个列表的开头留下未使用的零或空列表
用于(currentItem)
的循环将成为用于(currentClass)
的循环。数组最佳和解决方案
将由currentClass
索引,而不是currentItem
实际上,选项2
的值将被计算为几个选项中的最佳选项,每个类别项目一个:
double option2=整数.MIN_值;
对于(CurrTeNTEM=1;CurristMe:P>),解决这个问题的方法是将类<代码> 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]);
intdp[n][W+1]={0};
//项的基本条件=0
对于(int i=0;ithanks for reply!如果我在您修改的算法版本中理解正确,您将根据最大容量检查项目的权重,如果w可以通过最大值v实现:
,但这会发生在您迭代类项目之前。因此我不确定该如何工作。我已经包含了我的代码,所以我的算法可能是有点不同,你可以看看我做了什么。谢谢!@WildGoat:我添加了一些指针,说明这种方法会对你的代码产生什么影响。非常感谢,我正在尝试理解你的解决方案,并对我现有的代码进行更改。我会让你知道它是如何进行的。感谢你提供了如此有建设性的答案!这应该如何工作?对于starters,类中没有单一的“最佳”项。例如,一个类可能包含一个权重为3且值为5的项,另一个权重为5且值为8的项。您事先不知道哪一个“更好”当你的能力有限时,@Gassa这是一个DP,我们不是预先决定,而是从一个类中单独选择每个项目,检查结果并选择为特定子问题提供最大权重的项目。这与原始背包问题类似,但只考虑一个类中的一个或一个项目都不考虑。你能告诉我你没有从伪代码中得到什么吗对不起,我发现文本(“从类中选择最佳项”)令人困惑:它读起来就像“每个类中只有一个最佳项”.所以,我没有太多考虑代码。现在我读了代码,它似乎做了正确的事情。@Vikramhat,你对这个有什么想法吗-?谢谢。