题解 | #24点游戏算法#

24点游戏算法

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

  • 实数除法,包括小数,必须除尽
  • 依次遍历,递归计算:加减乘除和后,剩下的数字是否能组成
  • 递归计算:除当前数,剩下数组成的数组和加减乘除后的和

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Scanner;

/**
 * class com.sloera.nowcoder
 * user sloera
 * date 2022/2/22
 */
public class Main {
  public static void main(String[] args) throws ScriptException {
    // 7 9 10 9
    Scanner in = new Scanner(System.in);
    // 注意 hasNext 和 hasNextLine 的区别
    int[] num = new int[4];
    while (in.hasNextInt()) { // 注意 while 处理多个 case
      num[0] = in.nextInt();
      num[1] = in.nextInt();
      num[2] = in.nextInt();
      num[3] = in.nextInt();
      final boolean b = canSum(num, 24, false);
      // final boolean b = canSumByEval(num, 24);
      System.out.println(b ? "true" : "false");
    }
  }

  /**
   * 通过eval计算结果,先穷举出所有的可能,再计算
   * 此种方法表明,可以有括号。1 2 10 2示例输出为true。无括号时,无法得出。
   *
   * @param num
   * @param total
   * @return
   * @throws ScriptException
   */
  private static boolean canSumByEval(int[] num, int total) throws ScriptException {
    int sum = num[0] + num[1] + num[2] + num[3];
    char[] operators = new char[]{'+', '-', '*', '/'};
    final ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
    for (int i = 0; i < num.length; i++) {
      for (int j = 0; j < num.length; j++) {
        // 数字只能用一次
        if (j != i) {
          for (int k = 0; k < num.length; k++) {
            // 数字只能用一次
            if (k != i && k != j) {
              // 循环出所有的数字组合。 接着进行所有的符号组合
              for (int l = 0; l < operators.length; l++) {
                for (int m = 0; m < operators.length; m++) {
                  for (int n = 0; n < operators.length; n++) {
                    final String script = "" + num[i] + operators[l] + num[j] + operators[m] + num[k] + operators[n] + (sum - num[i] - num[j] - num[k]);
                    final Object eval = js.eval(script);
                    System.out.println(script + "\t" + eval);
                    if (Double.valueOf(eval.toString()).intValue() == total) {
                      return true;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return false;
  }

  /**
   * 计算是否可以得到对应的值
   *
   * 7 9 10 9 结果有问题
   *
   * @param addFlag 加减标记。如果外面的运算是乘除,则不可加减。{@code true} 不能有加减
   * @return boolean
   * @date 2022/2/23
   */
  private static boolean canSum(int[] num, int total, boolean addFlag) {
    addFlag = false;
    if (num.length == 0) {
      return 0 == total;
    }
    if (num.length == 1) {
      return num[0] == total;
    }
    for (int i = 0; i < num.length; i++) {
      // a * 4 = 24; a = 24 / 4 && 24 % 4 == 0
      final int[] nextNum = generateNum(num, i);
      if ((total % num[i] == 0 && canSum(nextNum, total / num[i], true)) || canSum(nextNum, num[i] * total, true) || (!addFlag && (canSum(nextNum, total - num[i], false) || canSum(nextNum, total + num[i], false)))) {
        return true;
      }
      // num[i] = 4
      // a / 4 = 24; a = 4 * 24 ~ (4 * 25) - 1
      // 实数除法, 所以只能完全相等
      // for (int j = num[i] * total; j < num[i] * (total + 1); j++) {
      //   if (canSum(generateNum(num, i), j, true)) {
      //     return true;
      //   }
      // }
    }
    return false;
  }

  /**
   * 生成非当前索引的数组
   *
   * @return int[]
   * @date 2022/2/22
   */
  private static int[] generateNum(int[] num, int index) {
    if (num.length <= 1) {
      return new int[]{};
    }
    final int[] ints = new int[num.length - 1];
    int j = 0;
    for (int i = 0; i < num.length; i++) {
      if (i != index) {
        ints[j++] = num[i];
      }
    }
    return ints;
  }


}
全部评论

相关推荐

头像
11-27 14:28
长沙理工大学
刷算法真的是提升代码能力最快的方法吗?&nbsp;刷算法真的是提升代码能力最快的方法吗?
牛牛不会牛泪:看你想提升什么,代码能力太宽泛了,是想提升算法能力还是工程能力? 工程能力做项目找实习,算法也分数据结构算法题和深度学习之类算法
点赞 评论 收藏
分享
一个菜鸡罢了:哥们,感觉你的简历还是有点问题的,我提几点建议,看看能不能提供一点帮助 1. ”新余学院“别加粗,课程不清楚是否有必要写,感觉版面不如拿来写一下做过的事情,教育经历是你的弱势就尽量少写 2. “干部及社团经历”和“自我评价”删掉 3. 论文后面的“录用”和“小修”啥的都删掉,默认全录用,问了再说,反正小修毕业前肯定能发出来 4. 工作经验和研究成果没有体现你的个人贡献,着重包装一下个人贡献
点赞 评论 收藏
分享
评论
点赞
1
分享
正在热议
# 25届秋招总结 #
443459次浏览 4523人参与
# 春招别灰心,我们一人来一句鼓励 #
42266次浏览 539人参与
# 北方华创开奖 #
107476次浏览 600人参与
# 地方国企笔面经互助 #
7973次浏览 18人参与
# 同bg的你秋招战况如何? #
77249次浏览 569人参与
# 实习必须要去大厂吗? #
55816次浏览 961人参与
# 阿里云管培生offer #
120461次浏览 2220人参与
# 虾皮求职进展汇总 #
116395次浏览 887人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11702次浏览 289人参与
# 实习,投递多份简历没人回复怎么办 #
2455021次浏览 34861人参与
# 提前批简历挂麻了怎么办 #
149962次浏览 1979人参与
# 在找工作求抱抱 #
906124次浏览 9423人参与
# 如果公司给你放一天假,你会怎么度过? #
4764次浏览 55人参与
# 你投递的公司有几家约面了? #
33209次浏览 188人参与
# 投递实习岗位前的准备 #
1196058次浏览 18550人参与
# 机械人春招想让哪家公司来捞你? #
157650次浏览 2267人参与
# 双非本科求职如何逆袭 #
662406次浏览 7397人参与
# 发工资后,你做的第一件事是什么 #
12808次浏览 62人参与
# 工作中,努力重要还是选择重要? #
35929次浏览 384人参与
# 简历中的项目经历要怎么写? #
86943次浏览 1516人参与
# 参加完秋招的机械人,还参加春招吗? #
20154次浏览 240人参与
# 我的上岸简历长这样 #
452080次浏览 8089人参与
牛客网
牛客企业服务