最佳递归回溯

问题描述 投票:0回答:1

我通过回溯所有可能的解决方案解决了背包问题的一种变化。基本上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;
            }
}
java recursion optimization backtracking
1个回答
0
投票
  1. 恕我直言,但您在优化低效算法上所做的努力只能描述为精打细算。您不会通过强力解决任何体面大小的背包问题,而且早日返回还不够。我已经提到了一种在CodeReview SE上编写高效程序的方法。这需要付出很大的努力,但是您必须做您必须做的事。
  2. 话虽如此,我建议您将arr编写为控制台,以便对序列进行故障排除。看起来,当您返回索引i-1时,i处的元素仍设置为1,并且您估计的是上限而不是下限。可能进行以下更改:替换您的代码

    for (int i = 0; i <= 1; i++) {
        arr[fromIndex] = i;
        generate(fromIndex + 1);
    }
    

    with

    arr[fromIndex] = 1;
    generate(fromIndex + 1);
    arr[fromIndex] = 0;
    generate(fromIndex + 1);
    

这将它变成一种贪婪算法:您不是从0000000开始,而是从1111111开始。显然,当您存储globalBestValue时,应该存储给出它的实际数据。但是主要建议是:当您的算法行为异常时,跟踪就是您的朋友。

© www.soinside.com 2019 - 2024. All rights reserved.