Java 从一组给出最小浪费量的数字中找出
下面将向此方法传递一个集合,并传入一段长度的条。解决方案应输出集合中的数字,如果从棒长度中移除集合中的某些数字,则该集合中的数字将给出最小的浪费量。所以,棒长10,集合包括6,1,4,所以解是6和4,损耗是0。我遇到了一些麻烦的条件,以回溯通过设置。我还尝试使用损耗全局变量来帮助回溯,但没有成功 SetInt是一个手动创建的集合实现,它可以添加、删除、检查集合是否为空以及从集合中返回最小值Java 从一组给出最小浪费量的数字中找出,java,recursion,backtracking,Java,Recursion,Backtracking,下面将向此方法传递一个集合,并传入一段长度的条。解决方案应输出集合中的数字,如果从棒长度中移除集合中的某些数字,则该集合中的数字将给出最小的浪费量。所以,棒长10,集合包括6,1,4,所以解是6和4,损耗是0。我遇到了一些麻烦的条件,以回溯通过设置。我还尝试使用损耗全局变量来帮助回溯,但没有成功 SetInt是一个手动创建的集合实现,它可以添加、删除、检查集合是否为空以及从集合中返回最小值 /* * To change this template, choose Tools | Templat
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package recback;
public class RecBack {
public static int WASTAGE = 10;
public static void main(String[] args) {
int[] nums = {6,1,4};
//Order Numbers
int barLength = 10;
//Bar length
SetInt possibleOrders = new SetInt(nums.length);
SetInt solution = new SetInt(nums.length);
//Set Declarration
for (int i = 0; i < nums.length; i++)possibleOrders.add(nums[i]);
//Populate Set
SetInt result = tryCutting(possibleOrders, solution, barLength);
result.printNumbers();
}
private static SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthleft)
{
SetInt clonedSet = possibleOrders.cloneSet(); //initialise selection of candidates
for (int i = 0; i < possibleOrders.numberInSet(); i++) // the repeat
{
int a = clonedSet.min(); //select next candidate
if (a <= lengthleft) //if accecptable
{
solution.add(a); //record candidate
lengthleft -= a;
clonedSet.remove(a); //remove from original set
if (!clonedSet.isEmpty()) //solution not complete
{
WASTAGE +=a;
tryCutting(clonedSet, solution, lengthleft);//try recursive call
if (lengthleft > WASTAGE)//if not successfull
{
WASTAGE += a;
solution.remove(a);
}
} //solution not complete
}
} //for loop
return solution;
}
}
你有几个问题 一个是这条线: int a=clonedSet.min//选择下一个候选人 如果你浏览一下你的例子,它会先找到值1并使用它,所以会使用1和4,但6不会
你最好寻找最大值我同意詹姆斯的观点,你不需要/不想要循环。据我所知,您的“tryCutting”算法包含一个可能的订单列表、正在考虑的当前解决方案以及如果您要剪切当前解决方案所剩下的长度。然后你需要: 从图中删除最短的切口 命令。如果它比剩下的长度长,不要再尝试了。否则 第一种情况:你没有完成任务 那次尝试用新的 订单列表和相同的当前 长 第二种情况:你确实做到了 那个伤口。将其添加到当前 解决方案并尝试使用新订单列表和长度进行剪切 减少了那部分。最后采取 它将再次关闭当前解决方案,以便 回溯 走捷径 返回订单进行回溯 现在,对于您尝试的每个案例,请对照您迄今为止的全球最佳案例检查剩余长度。它比用当前解决方案的克隆更新全局解决方案更短 这将为您提供单一的最佳解决方案,或者如果有几个同样好的解决方案,则提供其中一个。要获得所有解决方案,您需要一个全局SETINT列表。如果找到比当前解决方案更好的解决方案,请清除列表并添加新的解决方案。如果它等于当前最佳值,只需添加它即可 下面是代码:
public static void main(String[] args) {
int[] nums = {6,1,4}; //Order Numbers
int barLength = 10; //Bar length
bestSolution = new HashSet<SetInt>();
bestWastage = barLength;
SetInt possibleOrders = new SetInt(nums.length);
SetInt solution = new SetInt(nums.length); //Set Declarration
for (int i = 0; i < nums.length; i++) {
possibleOrders.add(nums[i]); //Populate Set
}
tryCutting(possibleOrders, solution, barLength);
for (SetInt result : bestSolution) {
result.printNumbers();
}
}
private static int bestWastage;
private static Set<SetInt> bestSolution;
private static void tryCutting(SetInt possibleOrders, SetInt solution, int lengthleft) {
if (lengthleft < bestWastage) {
// Better than the best solution
bestWastage = lengthleft;
bestSolution.clear();
bestSolution.add(solution.cloneSet());
} else if (lengthleft == bestWastage) {
// Just as good as the best solution
bestSolution.add(solution.cloneSet());
}
int a = possibleOrders.min(); //select next candidate
if (a <= lengthleft) { // If acceptable
possibleOrders.remove(a); // Remove it
tryCutting(possibleOrders, solution, lengthleft); // Try without that cut
solution.add(a); // add to the solution
tryCutting(possibleOrders, solution, lengthleft - a); // Try with that cut
solution.remove(a); // remove again
possibleOrders.add(a); // add the candidate back on again
}
}
这里的问题是它必须回溯,因此,如果值没有达到最佳结果,则刚刚添加到解决方案中的结果将再次删除。以便回溯和测试。我们被告知,它可以用最小结果完成。也不应该是静态的,那是我的错。最后,循环应该测试每个可能的解,因此如果集合为2,6,2,4;可以找到的解决方案是:6,4&6,2,2我希望这是有意义的!如果你愿意,我将不胜感激。我自己用和你相似的方法计算出来的。我添加了第二个递归调用,但没有实现哈希集。然而,我认为如果我这样做,它将帮助我存储多个解决方案。非常感谢。