使用DFS求解“24点游戏算法”

24点游戏算法

http://www.nowcoder.com/questionTerminal/fbc417f314f745b1978fc751a54ac8cb

使用DFS求解“24点游戏算法”

1.题目

问题描述:
给出4个1-10的数字,通过加减乘除,得到数字为24就算胜利
输入:
4个1-10的数字。[数字允许重复,但每个数字仅允许使用一次,测试用例保证无异常数字]
输出:
true or false

示例:
输入:

7 2 1 10

输出

true

2.思路精要:

  • (1)依次选择n[0],n[1],n[2],n[3]作为顶点。
  • (2)某次遍历后,如果最后节点的值为24则返回true,否则回溯。
  • (3)所有遍历后均得不到24,返回false。

3. 该题的图到底长什么样呢?

经过分析,如下图所示:

注意;图中的标注为各个顶点的初始值,遍历过程中顶点的值会发生变化。如按加法且路径为左上角-->右上角-->右下角-->左下角,则左下角顶点的值为n[0]+n[1]+n[2]+n[3]。因此,一次遍历后,最后节点的值等于24,就意味着可以得到24。

4.具体代码

// package org.jzy.huawei108;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            // 初始化数字数组和标志数组
            int[] nums = new int[4];
            int[] signs = new int[4];
            for (int i = 0; i < nums.length; i++) {
                nums[i] = scanner.nextInt();
            }

            boolean can = false; // 是否能得到24
            for (int i = 0; i < nums.length; i++) {
                signs[i] = 1;
                if (dfs(nums, signs, nums[i], 24)) {
                    can = true;
                    break;
                }
                signs[i] = 0;
            }
            System.out.println(can);// 输出结果
        }
    }

    /**
     * 深度优先算法逻辑
     *
     * @param nums     输入的4个数字
     * @param signs    访问标志数组
     * @param v        顶点的值
     * @param required 需要通过四则运算得到的数字
     * @return
     */
    private static boolean dfs(int[] nums, int[] signs, int v, int required) {
        boolean allVisited = true;// 四个角均被访问
        for (int sign : signs) {
            if (sign == 0) {
                allVisited = false;
            }
        }

        if (allVisited) {
            return v == required; // 在所有节点均被访问的前提下,判断最后的结果是否为所需要的结果。
        }

        // 访问所有的邻接顶点
        for (int i = 0; i < nums.length; i++) {
            if (signs[i] == 0) {
                signs[i] = 1;
                if (dfs(nums, signs, v + nums[i], required) // 加法
                        || dfs(nums, signs, v - nums[i], required) // 减法
                        || dfs(nums, signs, v * nums[i], required) // 乘法
                        || nums[i] != 0 && v % nums[i] == 0 && dfs(nums, signs, v / nums[i], required)/* 除法 */) {
                    return true;// 如果可以通过四则运算得到需要的结果,则返回true。
                }
                signs[i] = 0; // 如果不能通过四则运算得到,则进行回溯。
            }
        }

        return false;//当所有情况均得不到需要的结果,返回false。
    }
}
全部评论
代码是错的,比如5 5 5 5,5 * 5 - (5/5)= 24.
5 回复 分享
发布于 2021-03-22 19:19
括号问题没有解决,简单的把无括号优先级由大到小的算式转化为迭代计算。 本质:(((xsx)sx)sx) 其中x表示[1,10]数字,s表示[*/+-]符号
2 回复 分享
发布于 2020-12-09 14:42
想问一下,为什么4个数遍历进去dfs,就一定能求得最优解呢,因为除了第一个数,剩下的三个都是按照array里面的顺序的,可能会导致求不到最优解吗?
点赞 回复 分享
发布于 2020-12-25 14:02
问下,+-*/四种情况都考虑为何还要进行回溯
点赞 回复 分享
发布于 2022-04-10 17:05
(9+10)*9/7=24,为啥是false?
点赞 回复 分享
发布于 2022-05-30 00:20
虽然有几个特例不对,但是就DFS实现地很好
点赞 回复 分享
发布于 2022-06-17 01:52
必须要把4个数全部用完吗?
点赞 回复 分享
发布于 2022-08-10 18:00

相关推荐

10-27 17:26
东北大学 Java
点赞 评论 收藏
分享
评论
20
2
分享
牛客网
牛客企业服务