题解 | #24点运算#

利用dfs计算全排列
1)计算四种运算符的可重复取(4取3)的全排列
2)计算4个数字的全排列,注意有可能四张牌相同
3)遍历每一种运算符排列和数字排列,有符合的情况则立即输出

import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 此题不同于24点游戏,此题只按照从左到右计算,不按照运算级运算
        // + - * /,四个符号里面选择三个,放在4个数字之间
        Scanner sc = new Scanner(System.in);
        String[] str = sc.nextLine().trim().split(" ");
        int[] pai = new int[4];
        for (int i = 0; i < 4; i++) {
            int len = str[i].length();
            if (len > 2) {
                System.out.println("ERROR");
                return;
            } else if (str[i].length() == 2) {
                pai[i] = 10;
            } else {
                char ch = str[i].charAt(0);
                if (Character.isDigit(ch)) {
                    pai[i] = ch - '0';
                } else {
                    if (ch == 'J') pai[i] = 11;
                    if (ch == 'Q') pai[i] = 12;
                    if (ch == 'K') pai[i] = 13;
                    if (ch == 'A') pai[i] = 1;
                }
            }
        }

        // 运算符全排列(可重复选的,4选3的)
        List<List<Character>> operationsList = new ArrayList<>();
        List<Character> opList = new ArrayList<>();
        Character[] operations = {'+', '-', '*', '/'};
        dfsOp(operationsList, opList, operations);

        // 计算牌的全排列
        List<List<Integer>> paisList = new ArrayList<>();
        List<Integer> pList = new ArrayList<>();
        boolean[] visited = new boolean[4];
        dfsPai(paisList, pList, pai, visited);

        for(List<Integer> p : paisList) {
            for (List<Character> op : operationsList) {
                if (compute(p,op)) {
                    printPai(p.get(0));
                    for (int i = 0; i < 3; i++) {
                        System.out.print(op.get(i));
                        printPai(p.get(i + 1));
                    }
                    return;
                }
            }
        }
        System.out.println("NONE");

    }


    public static void printPai(int num) {
        if (num == 1) System.out.print('A');
        if (num == 11) System.out.print('J');
        if (num == 12) System.out.print('Q');
        if (num == 13) System.out.print('K');
        if (num >= 2 && num <= 10) System.out.print(num);
    }


    /**
     * 计算运算符的全排列
     * 计算可重复选,4选3的全排列
     */
    public static void dfsOp(List<List<Character>> operationsList, List<Character> list, Character[] operations) {
        if (list.size() == 3) {
            operationsList.add(new ArrayList<>(list));
            return;
        }
        for (char c : operations) {
            list.add(c);
            dfsOp(operationsList, list, operations);
            list.remove(list.size() - 1);  // 回溯
        }
    }


    /**
     *  计算牌的全排列,不可重复的全排列
     */
    public static void dfsPai(List<List<Integer>> paisList, List<Integer> list, int[] pai, boolean[] visited) {
        if (list.size() == 4) {
            paisList.add(new ArrayList<>(list));
            return;
        }
        for (int i = 0; i < 4; i++) {
            if (!visited[i]) {
                list.add(pai[i]);
                visited[i] = true;
                dfsPai(paisList, list, pai, visited);

                list.remove(list.size() - 1);  // 回溯
                visited[i] = false;
            }
        }
    }


    /**
     * 判断表达式是否为24
     * 运算顺序从左至右,不包含括号,且整数除法属于整除
     */
    public static boolean compute(List<Integer> pList, List<Character> opList) {
        int result = pList.get(0);
        // 剩余三个数字和三个运算符
        for (int i = 0; i < 3; i++) {
            char op = opList.get(i);
            int sub = pList.get(i + 1);
            if (op == '+') {
                result = result + sub;
            } else if (op == '-') {
                result = result - sub;
            } else if (op == '*') {
                result = result * sub;
            } else {
                result = result / sub;
            }
        }
        return result == 24;
    }
}


全部评论

相关推荐

头像 头像
04-07 20:12
已编辑
同济大学 计算机类
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务