我通过回溯所有可能的解决方案解决了背包问题的一种变化。基本上0表示该物品不在背包中,1表示该物品在背包中。成本是背包中所有物品的价值,我们试图在拥有每个“类别”物品的同时实现最低的价值。每次找到所有类的组合时,我将计算所有项目的值,如果它小于globalBestValue,则保存该值。我是verify()
。
现在,我正在尝试优化可追溯的回溯。我的想法是遍历正在生成的数组,如果生成的数字的“成本”已经高于当前最佳值,则返回生成器,因此当前生成的组合不能成为新的最佳值。并且可以跳过。
但是,由于我的乐观态度,我的追踪并没有生成所有值,而是实际上跳过了我试图找到的“最佳”值。你能告诉我问题出在哪里吗?
private int globalBestValue = Integer.MAX_VALUE;
private int[] arr;
public KnapSack(int numberOfItems) {
arr = new int[numberOfItems];
}
private void generate(int fromIndex) {
int currentCost = 0; // my optimisation starts here
for (int i = 0; i < arr.length; i++) {
if (currentCost > globalBestValue) {
return;
}
if (arr[i] == 1) {
currentCost += allCosts.get(i);
}
} // ends here
if (fromIndex == arr.length) {
verify();
return;
}
for (int i = 0; i <= 1; i++) {
arr[fromIndex] = i;
generate(fromIndex + 1);
}
}
public void verify() {
// skipped the code verifying the arr if it's correct, it's long and not relevant
if (isCorrect == true && currentValue < globalBestValue) {
globalBestValue = currentValue;
}else{
return;
}
}
答案 0 :(得分:0)
话虽如此,我建议您将arr
编写为控制台,以便对序列进行故障排除。看起来,当您返回索引i-1
时,i
处的元素仍设置为1,并且您估计的是上限而不是下限。以下更改可能会起作用:替换您的代码
for (int i = 0; i <= 1; i++) {
arr[fromIndex] = i;
generate(fromIndex + 1);
}
使用
arr[fromIndex] = 1;
generate(fromIndex + 1);
arr[fromIndex] = 0;
generate(fromIndex + 1);
这使它变成一种贪婪算法:您不必以0000000
开头,而不必以1111111
开头。显然,在存储globalBestValue
时,应该存储给出它的实际数据。但是主要建议是:当您的算法行为异常时,跟踪就是您的朋友。