lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1. 题目

读题

 HJ67 24点游戏算法

 

考查点

 

2. 解法

思路

 

代码逻辑

 

具体实现

import java.util.Scanner;
import java.util.Arrays;

public class HJ67 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int[] nums = new int[4];
            for (int i = 0; i < 4; i++) {
                nums[i] = sc.nextInt();
            }
            System.out.println(solve(nums));
        }
        sc.close();
    }

    public static boolean solve(int[] nums) {
        Arrays.sort(nums); // 排序
        do {
            if (check(nums)) return true; // 检查当前排列是否满足条件
        } while (nextPermutation(nums)); // 生成下一个排列
        return false;
    }

    public static boolean check(int[] nums) {
        for (int i = 0; i < 4; i++) { // 枚举第一个运算符
            for (int j = 0; j < 4; j++) { // 枚举第二个运算符
                for (int k = 0; k < 4; k++) { // 枚举第三个运算符
                    double a = calc(nums[0], nums[1], i); // 计算第一个表达式
                    double b = calc(a, nums[2], j); // 计算第二个表达式
                    double c = calc(b, nums[3], k); // 计算第三个表达式
                    if (Math.abs(c - 24) < 1e-6) return true; // 如果结果等于24,返回true

                    a = calc(nums[0], nums[1], i); // 计算第一个表达式
                    b = calc(nums[2], nums[3], k); // 计算第三个表达式
                    c = calc(a, b, j); // 计算第二个表达式(考虑括号)
                    if (Math.abs(c - 24) < 1e-6) return true; // 如果结果等于24,返回true
                }
            }
        }
        return false;
    }

    public static double calc(double x, double y, int op) { // 根据运算符计算两个数的结果
        switch (op) {
            case 0: return x + y;
            case 1: return x - y;
            case 2: return x * y;
            case 3: return x / y;
            default: return 0;
        }
    }

    public static boolean nextPermutation(int[] nums) { // 生成下一个排列(字典序)
        int n = nums.length;
        int i = n - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) { // 找到第一个逆序对
            i--;
        }
        if (i >= 0) { // 如果不是最后一个排列
            int j = n - 1;
            while (j > i && nums[j] <= nums[i]) { // 找到第一个大于nums[i]的数
                j--;
            }
            swap(nums, i, j); // 交换两个数
        } else { // 如果是最后一个排列,返回false
            return false;
        }
        reverse(nums, i + 1, n - 1); // 反转后面的部分
        return true;
    }

    public static void swap(int[] nums, int i, int j) { // 交换数组中两个数的位置
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public static void reverse(int[] nums, int i, int j) { // 反转数组中一段区间的元素
        while (i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }
}

自行实现 

3. 总结

posted on 2023-07-25 12:06  白露~  阅读(76)  评论(0编辑  收藏  举报