我正在寻找一种算法,以找到一组列表的最佳组合(权重最高)。例如,假设我们有项目“ A”,“ B”和“ C”,我们得到4个A,2个B和3个C。一些可能的组合可能是:
{A,B,C},{A,B,C},{A,C},{A}
{A,B},{A,B,C},{A,C},{A,C}
然后权重基于每套物品的数量,例如:
1件:5
2个项目:15
3个项目:20
因此,在这种情况下,第一个组合的权重为20 + 20 + 15 + 5 = 60,第二个组合的权重为15 + 20 + 15 + 15 = 65。贪婪算法在这种情况下不起作用,因为在某些情况下,寻找最大数量的商品并不能返回最佳组合。
有什么想法吗?
答案 0 :(得分:0)
我使用递归解决了这个问题。
这些变量定义了问题(静态变量):
private static boolean[] BEST_SOLUTION_SO_FAR = null;
private static int BEST_WEIGHT_SO_FAR = 0;
private static String[][] POSSIBLE_SETS = {{"A","B","C"},{"A","B","C"},{"A","C"},{"A"},{"A","B"},{"A","B","C"},{"A","C"},{"A","C"}};
private static Map<String, Integer> MAX_OF_EACH_ITEM = new HashMap<>();
static {
MAX_OF_EACH_ITEM.put("A", 4);
MAX_OF_EACH_ITEM.put("B", 2);
MAX_OF_EACH_ITEM.put("C", 3);
}
这是主要方法(它将为递归的开始进行所有设置):
public static void main(String[] args) {
BEST_WEIGHT_SO_FAR = 0;
BEST_SOLUTION_SO_FAR = null;
// start the recursion
buildSolution(new boolean[POSSIBLE_SETS.length], new HashMap<>());
// print solution
System.out.println("BEST SOLUTION : ");
for (int i = 0; i < POSSIBLE_SETS.length; i++) {
if(BEST_SOLUTION_SO_FAR[i]){
System.out.println(Arrays.toString(POSSIBLE_SETS[i]));
}
}
}
这是递归方法:
private static void buildSolution(boolean[] isSelected, Map<String, Integer> itemsUsed){
boolean canBeExpanded = false;
for (int i = 0; i < isSelected.length; i++) {
// check whether another set can be added
if(!isSelected[i]){
// calculate new numbers of items used
Map<String, Integer> itemsUsedB = new HashMap<>(itemsUsed);
for (int j = 0; j < POSSIBLE_SETS[i].length; j++) {
String key = POSSIBLE_SETS[i][j];
if(itemsUsedB.containsKey(key))
itemsUsedB.put(key, itemsUsedB.get(key) + 1);
else
itemsUsedB.put(key, 1);
}
// check whether this is possible
boolean isPossible = true;
for(String key : MAX_OF_EACH_ITEM.keySet()){
if(itemsUsedB.containsKey(key) && itemsUsedB.get(key) > MAX_OF_EACH_ITEM.get(key)){
isPossible = false;
break;
}
}
// if not possible attempt next
if(!isPossible)
continue;
// mark this solution as expandable
canBeExpanded = true;
// mark as selected
isSelected[i] = true;
// recurse
buildSolution(isSelected, itemsUsedB);
// undo mark
isSelected[i] = false;
}
}
// a solution that can no longer be expanded was found
if(!canBeExpanded){
int w = 0;
int[] setSizeWeight = {0,5,15,20};
for (int i = 0; i < isSelected.length; i++) {
w += isSelected[i] ? setSizeWeight[POSSIBLE_SETS[i].length] : 0;
}
if(w > BEST_WEIGHT_SO_FAR){
BEST_WEIGHT_SO_FAR = w;
BEST_SOLUTION_SO_FAR = Arrays.copyOf(isSelected, isSelected.length);
}
}
}
它输出:
最佳解决方案
[A,B,C]
[A,C]
[A,B]
[A,C]
体重为65。