题解 | #24点游戏算法#

24点游戏算法

https://www.nowcoder.com/practice/fbc417f314f745b1978fc751a54ac8cb?tpId=37&tqId=21290&rp=1&ru=%2Fexam%2Foj%2Fta&qru=%2Fexam%2Foj%2Fta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D2%26pageSize%3D50%26search%3D%26tpId%3D37%26type%3D37&difficulty=undefined&judgeStatus=undefined&tags=&title=&dayCountBigMember=%E8%BF%9E%E7%BB%AD%E5%8C%85%E6%9C%88

递归+回溯+DFS(有分析带括号情况)

偷得别人答案,但是那个老哥没有解决所有情况。

本代码完美解决题目问题,适应所有情况。

同时追溯显示了四个数字的运算情况。(记得去掉输出代码的//)

只能说递归还是好用的 虽然空间消耗大,但是代码还算简洁、整齐。

很适合我这种强迫症,O(∩_∩)O哈哈~。

import java.util.*;
import java.io.*;
public class Main {
    private static int[] nums = new int[4];
    private static boolean[] visit = new boolean[4];
    private static boolean[] visit2 = new boolean[4];
    private static int flag = 0;
    private static int flag2 = 0;
  	//显示四个数字的 出现顺序 和各个运算符
    private static String z = "", x = "", c = "", v = "";
  	//显示四个数字的 出现顺序 和各个运算符, b为两括号相运算的实际情况。
    private static String z2 = "", x2 = "", c2 = "", v2 = "", b = "";
    private static int count = 0;

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            String[] a = in.nextLine().split(" ");
            for (int i = 0; i < 4; i ++)
                nums[i] = Integer.parseInt(a[i]);
            dfs(0, 0);
            dfs3(0, 0, 0, 0);

            System.out.println( flag == 1 || flag2 == 1);
            //System.out.println( z + " / " + x + " / " + c + " / " + v );
            //System.out.println( z2 + " / " + x2 + " / " + c2 + " / " + v2 );
            //System.out.println(b);
            //System.out.println( count );
        }

    }

    // tmp是前面n个数字运算结果,u表示已经使用了多少个数字。 不考虑括号。
    static boolean dfs(int u, float tmp) {
        //count++;
        //System.out.println("1");
        // 递归终止条件:已经使用了数组四个元素,同时结果为24,满足题意
        if (tmp == 24 && u == 4) {
            flag = 1;
            return true;
        }

        for (int i = 0; i < 4; i ++) {
            if (visit[i] ==
                    false) {    //没访问过才执行。 都访问过了就跳过此if代码块,还不达成条件 就返回false。
                visit[i] = true;
                // 加减乘除当前数字num[i]
                if ( dfs(u + 1, tmp +
                         nums[i]) ) {  //四个数字运算完后不符合 返回false,不执行此if代码块
                    z += "(" + u + ")" + "+" + nums[i] + " ";
                    return true;    //退出语句。 满足递归终止条件, 即满足if , 返回true 一路退出递归。
                }
                if (tmp != 0) {
                    if (dfs(u + 1, tmp - nums[i])) {
                        x += "(" + u + ")" + "-" + nums[i] + " ";
                        return true;
                    }
                    if (dfs(u + 1, tmp * nums[i])) {
                        c += "(" + u + ")" + "*" + nums[i] + " ";
                        return true;
                    }
                    if (dfs(u + 1, tmp / nums[i])) {
                        v += "(" + u + ")" + "/" + nums[i] + " ";
                        return true;
                    }
                }
                /*if( dfs(u + 1, tmp + nums[i]) ||
                        dfs(u + 1, tmp - nums[i])  ||
                        dfs(u + 1,tmp * nums[i]) ||
                        dfs(u + 1, tmp / nums[i])){
                    return true;
                }*/
                // 相当于回溯。 当前四个数字的组合未能符合 则回溯
                visit[i] = false;
            }
        }
        return false;   //if语句没通过 试试其他运算了
    }

    static boolean dfs2(int u, float tmp1, float tmp2, float tmp) {
        for (int i = 0; i < 4; i ++) {
            tmp1 += nums[i];
            visit2[i] = true;
            for (int j = i + 1; j < 4; j ++) {
                tmp1 += nums[j];
                visit2[j] = true;

                for (int x = 0; x < 4; x ++) {
                    if (visit2[x] == false) {
                        tmp2 += nums[x];
                    }
                }
                tmp = tmp1 + tmp2;
                if (tmp == 24) {
                    return true;
                }
            }
        }

        return false;
    }

  	//考虑有括号的情况
    static boolean dfs3(int u, float tmp1, float tmp2, float tmp) {
        // 递归终止条件:已经使用了数组四个元素,两两运算,再互相运算同时结果为24,满足题意
        if (tmp1 + tmp2 == 24 && u == 4) {
            flag2 = 1;
            b += tmp1 + "+" + tmp2;
            return true;
        }
        if (tmp1 - tmp2 == 24 && u == 4) {
            flag2 = 1;
            b += tmp1 + "-" + tmp2;
            return true;
        }
        if (tmp1 * tmp2 == 24 && u == 4) {
            flag2 = 1;
            b += tmp1 + "*" + tmp2;
            return true;
        }
        if (tmp1 / tmp2 == 24 && u == 4) {
            flag2 = 1;
            b += tmp1 + "/" + tmp2;
            return true;
        }


        for (int i = 0; i < 4; i ++) {
            if (visit2[i] == false) {
                visit2[i] = true;
                // 加减乘除当前数字num[i]
                if (u < 2) {	//选好前两个数字,进行运算。
                    if (dfs3(u + 1, tmp1 + nums[i], 0,
                             0)) {   //四个数字运算完后不符合 返回false,不执行此if代码块
                        z2 += "(" + u + ")" + "+" + nums[i] + " ";
                        return true;    //退出语句。
                    }
                    if (tmp1 != 0) {
                        if (dfs3(u + 1, tmp1 - nums[i], 0, 0)) {
                            x2 += "(" + u + ")" + "-" + nums[i] + " ";
                            return true;
                        }
                        if (dfs3(u + 1, tmp1 * nums[i], 0, 0)) {
                            c2 += "(" + u + ")" + "*" + nums[i] + " ";
                            return true;
                        }
                        if (dfs3(u + 1, tmp1 / nums[i], 0, 0)) {
                            v2 += "(" + u + ")" + "/" + nums[i] + " ";
                            return true;
                        }
                    }
                } else {	//选好后两个数字,进行运算。
                    if (dfs3(u + 1, tmp1, tmp2 + nums[i],
                             0)) {   //四个数字运算完后不符合 返回false,不执行此if代码块
                        z2 += "(" + u + ")" + "+" + nums[i] + " ";
                        return true;    //退出语句。
                    }
                    if (tmp2 != 0) {
                        if (dfs3(u + 1, tmp1, tmp2 - nums[i], 0)) {
                            x2 += "(" + u + ")" + "-" + nums[i] + " ";
                            return true;
                        }
                        if (dfs3(u + 1, tmp1, tmp2 * nums[i], 0)) {
                            c2 += "(" + u + ")" + "*" + nums[i] + " ";
                            return true;
                        }
                        if (dfs3(u + 1, tmp1, tmp2 / nums[i], 0)) {
                            v2 += "(" + u + ")" + "/" + nums[i] + " ";
                            return true;
                        }
                    }

                }
                // 相当于回溯
                visit2[i] = false;
            }
        }
        return false;
    }
}  

#晒一晒我的offer#
全部评论
代码有点多 但其实主要是注释和优化。 感觉还能再优化。比如 初始0不能进行-*/运算。
点赞 回复 分享
发布于 2023-12-13 22:26 湖南

相关推荐

努力学习的小绵羊:我反倒觉得这种挺好的,给不到我想要的就别浪费大家时间了
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务