一尘不染

如何设计一种算法来计算倒计时样式数学数谜题

algorithm

我一直想这样做,但是每当我开始思考这个问题时,由于它的指数性质,它令我震惊。

我希望能够理解和编写的问题解决程序是针对倒数数学问题的:

给定一组从X1到X5的数字,计算如何使用数学运算将它们进行组合以使Y。您可以应用乘法,除法,加法和减法。

那么如何1,3,7,6,8,3制作348呢?

答:(((8 * 7) + 3) -1) *6 = 348

如何编写可以解决此问题的算法?尝试解决此类问题时从哪里开始?设计这样的算法时,您需要考虑哪些重要的考虑因素?


阅读 252

收藏
2020-07-28

共1个答案

一尘不染

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()函数递归的每个级别中处理的数字序列或(和)运算进行排序。

这种启发式函数的示例是例如中间结果与总目标结果之间的差异。

但是,这种方式只能改善最佳情况和平均情况下的复杂性。最坏的情况仍然是复杂性。

最坏的情况下,可以通过某种分支切割来提高复杂性。我不确定在这种情况下是否有可能。

2020-07-28