HJ67 24点游戏算法 | 题解

看了所有Java版本的题解,没有满意的,只好自己写了一个。
  • 游戏的第一步是挑出两个数,算出一个新数替代这两个数。

  • 然后,在三个数中玩 24 点,再挑出两个数,算出一个数替代它们。

  • 然后,在两个数中玩 24 点……

很明显的递归思路。每次递归都会挑出两个数,我们尝试挑出不同的两数组合

  • 挑 1、2,基于它,继续递归。
  • 挑 1、3,基于它,继续递归。
  • 挑 ……

即通过两层 for 循环,枚举所有的两数组合,展开出不同选择所对应的递归分支。

挑出的每一对数,我们…

  • 枚举出所有可能的运算操作:加减乘除…——(对应不同的递归调用)
  • 逐个尝试每一种运算——(选择进入一个递归分支)
  • 传入长度变小的新数组继续递归——(递归计算子问题)
  • 当递归到只剩一个数——(到达了递归树的底部),看看是不是 24 。
    • 是就返回 true——结束当前递归,并且控制它不进入别的递归分支,整个结束掉。
    • 否则返回 false,离开错误的分支,进入别的递归分支,尝试别的运算。

剪枝小技巧

当递归返回 true,代表游戏成功,不用继续探索了,剩下的搜索分支全部砍掉。怎么做到?

  • 代码如下。标识变量isValid初始为 false,默认会执行||后面的递归。
  • 一旦某个递归返回真,isValid就变为真,由于||的短路特性,后面的递归不会执行。
  • 所有递归子调用都这么写,isValid就像一个开关,避免写很多判断语句。
isValid = isValid || judgePoint24([...newNums, n1 + n2]);
isValid = isValid || judgePoint24([...newNums, n1 - n2]);
isValid = isValid || judgePoint24([...newNums, n2 - n1]);
isValid = isValid || judgePoint24([...newNums, n1 * n2]);
// ...


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int[] nums = new int[4];
            for (int i = 0; i < nums.length; i++) {
                nums[i] = in.nextInt();
            }
            List<Double> list = new ArrayList<Double>();
            for (int num : nums) {
                list.add((double)num);
            }
            System.out.println(helper(list));
        }
    }

    public static boolean helper(List<Double> list) {
        if (list.size() == 1)
            return Math.abs(list.get(0) - 24) <= 0.00001;
        for (int i = 0; i < list.size(); i++) {
            for (int j = i + 1; j < list.size(); j++) {
                List<Double> tmp = new ArrayList<>(list);
                double b = tmp.remove(j), a = tmp.remove(i);
                boolean valid = false;
                tmp.add(a + b);
                valid |= helper(tmp);
                tmp.set(tmp.size() - 1, a - b);
                valid |= helper(tmp);
                tmp.set(tmp.size() - 1, a * b);
                valid |= helper(tmp);
                tmp.set(tmp.size() - 1, a / b);
                valid |= helper(tmp);
                tmp.set(tmp.size() - 1, b - a);
                valid |= helper(tmp);
                tmp.set(tmp.size() - 1, b / a);
                valid |= helper(tmp);
                if (valid)
                    return true;
            }
        }
        return false;
    }
}


全部评论

相关推荐

2024-12-20 18:56
已编辑
武汉轻工大学 后端
牛牛大啊:er图都冒出来了😂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务