题解 | #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;
  }


}
全部评论

相关推荐

totoroyyw:千年老妖😂
投递华为等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
1
分享
牛客网
牛客企业服务