我一直想这样做,但是每当我开始思考这个问题时,由于它的指数性质,它令我震惊。
我希望能够理解和编写的问题解决程序是针对倒数数学问题的:
给定一组从X1到X5的数字,计算如何使用数学运算将它们进行组合以使Y。您可以应用乘法,除法,加法和减法。
那么如何1,3,7,6,8,3制作348呢?
1,3,7,6,8,3
348
答:(((8 * 7) + 3) -1) *6 = 348。
(((8 * 7) + 3) -1) *6 = 348
如何编写可以解决此问题的算法?尝试解决此类问题时从哪里开始?设计这样的算法时,您需要考虑哪些重要的考虑因素?
Java中非常快速且肮脏的解决方案:
public class JavaApplication1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1, 3, 7, 6, 8, 3); for (Integer integer : list) { List<Integer> runList = new ArrayList<>(list); runList.remove(integer); Result result = getOperations(runList, integer, 348); if (result.success) { System.out.println(integer + result.output); return; } } } public static class Result { public String output; public boolean success; } public static Result getOperations(List<Integer> numbers, int midNumber, int target) { Result midResult = new Result(); if (midNumber == target) { midResult.success = true; midResult.output = ""; return midResult; } for (Integer number : numbers) { List<Integer> newList = new ArrayList<Integer>(numbers); newList.remove(number); if (newList.isEmpty()) { if (midNumber - number == target) { midResult.success = true; midResult.output = "-" + number; return midResult; } if (midNumber + number == target) { midResult.success = true; midResult.output = "+" + number; return midResult; } if (midNumber * number == target) { midResult.success = true; midResult.output = "*" + number; return midResult; } if (midNumber / number == target) { midResult.success = true; midResult.output = "/" + number; return midResult; } midResult.success = false; midResult.output = "f" + number; return midResult; } else { midResult = getOperations(newList, midNumber - number, target); if (midResult.success) { midResult.output = "-" + number + midResult.output; return midResult; } midResult = getOperations(newList, midNumber + number, target); if (midResult.success) { midResult.output = "+" + number + midResult.output; return midResult; } midResult = getOperations(newList, midNumber * number, target); if (midResult.success) { midResult.output = "*" + number + midResult.output; return midResult; } midResult = getOperations(newList, midNumber / number, target); if (midResult.success) { midResult.output = "/" + number + midResult.output; return midResult } } } return midResult; } }
更新
它基本上只是具有指数复杂性的简单蛮力算法。但是,您可以通过利用一些启发式函数来获得一些改进,这些启发式函数将帮助您对在getOperatiosn()函数递归的每个级别中处理的数字序列或(和)运算进行排序。
getOperatiosn()
这种启发式函数的示例是例如中间结果与总目标结果之间的差异。
但是,这种方式只能改善最佳情况和平均情况下的复杂性。最坏的情况仍然是复杂性。
最坏的情况下,可以通过某种分支切割来提高复杂性。我不确定在这种情况下是否有可能。