题解 | #24点游戏算法#
24点游戏算法
https://www.nowcoder.com/practice/fbc417f314f745b1978fc751a54ac8cb
首先感谢大神提出的问题,我个人一开始也忽略了两两组合的情况:
https://blog.nowcoder.net/n/d8686854e48b4d59bc9813f450e16a13?f=comment
针对上面大神的答案,我个人有两个改进思路:
1、整体拆成两部分判断:逐个计算判断与两两计算判断,且两两计算判断只考虑(n1 +/- n2) */÷ (n3 +/- n4) = 24这种情况,即括号里面的计算如果是乘或除,括号就没必要了,在逐个判断时就已经包括进去这种情况了;括号外面如果是加或减,两个括号就都没必要了,同上。(在括号内做减法时,只考虑n1-n2的情况,忽略n2-n1,与此同时忽略相减后的负号,因为最后乘或除能得到-24,就一定能得到24。这样只需要考虑(01、23)(02、13)(03、12)三种组合情况即可。)
2、全程整数运算,除法之前先判断能否整除,不考虑产生小数的情况(针对1/2*6*8=24的情况,后面轮询到1*6*8/2=24也能判断成功,所以前面可以不做1/2这一分支。)
import java.util.*;
public class Main {
static int[] arr = new int[4];// 用于接收传入的4个整数
static boolean[] used = new boolean[4];// 用于判断对应序号的整数有没有被使用。
static int count = 0;
int tmp = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
arr[0] = scanner.nextInt();
arr[1] = scanner.nextInt();
arr[2] = scanner.nextInt();
arr[3] = scanner.nextInt();
if (help2(0, 0, 0)) {
System.out.println(true);
} else {// 计算 (n1 +/- n2) */÷ (n3 +/- n4) = 24的情况
System.out.println(help22(0, 0, 0, 0 ,0));
}
}
/**
* 正向逐个处理
*/
public static boolean help2 (int n1, int flag, int n2) {// 0-初始; 1-加; 2-减; 3-乘; 4-除
if (count == 1) {
n1 = n2;
} else {
if (flag == 1) {
n1 = n1 + n2;
} else if (flag == 2) {
n1 = n1 - n2;
} else if (flag == 3) {
n1 = n1 * n2;
} else if (flag == 4) {
n1 = n1 / n2;
}
}
if (count < 4) {
for (int i=0; i<4; i++) {// i:取数
if (used[i]) {
continue;
}
count ++;
used[i] = true;
for (int j=4; j>0; j--) {// j:四则运算标志
if (j == 4) {
if (n1 % arr[i] == 0) {
if (help2(n1, j, arr[i])) {
return true;
}
}
} else {
if (help2(n1, j, arr[i])) {
return true;
}
}
}
count --;
used[i] = false;
}
} else if (count == 4 && n1 ==24) {
return true;
}
return false;
}
/**
*
* @param n1 与arr[0]计算的下标值
* @param n2 不与arr[0]计算的下标值之一
* @param n3 不与arr[0]计算的下标值之一
* @param flag1 arr[0]与arr[n1]的运算(0-初始化; 1-加; 2-减)
* @param flag2 另外两个值的运算(0-初始化; 1-加; 2-减)
* @return
*/
public static boolean help22(int n1, int n2, int n3, int flag1, int flag2) {
if (flag1 == 0 && flag2 ==0) {
for (int f1=1; f1<=2; f1++) {// flag1
for (int f2=1; f2<=2; f2++) {// flag2
if (help22(1, 2, 3, f1, f2)) {
return true;
}
if (help22(2, 1, 3, f1, f2)) {
return true;
}
if (help22(3, 1, 2, f1, f2)) {
return true;
}
}
}
} else {
int tmp1 = 0, tmp2 = 0;
if (flag1 == 1) {
tmp1 = arr[0] + arr[n1];
} else if (flag1 == 2) {
tmp1 = arr[0] - arr[n1];
if (tmp1 < 0) {
tmp1 = tmp1 * -1;
}
}
if (flag2 == 1) {
tmp2 = arr[n2] + arr[n3];
} else if (flag2 == 2) {
tmp2 = arr[n2] - arr[n3];
if (tmp2 < 0) {
tmp2 = tmp2 * -1;
}
}
if (tmp1 * tmp2 == 24
|| (tmp2 != 0 && tmp1 % tmp2 == 0 && tmp1 / tmp2 == 24)
|| (tmp1 != 0 && tmp2 % tmp1 == 0 && tmp2 / tmp1 == 24)) {
return true;
}
}
return false;
}
}
查看1道真题和解析