题目描述
给出4个1-10的数字,通过加减乘除,得到数字为24就算胜利
输入:
4个1-10的数字。[数字允许重复,测试用例保证无异常数字]
输出:
true or false
输入描述
输入4个int整数
输出描述
返回能否得到24点,能输出true,不能输出false
输入例子
7 2 1 10
输出例子
true
算法实现
import java.util.LinkedList;
import java.util.Scanner;
/**
* Author: 王俊超
* Date: 2016-05-04 12:09
* 优快云: http://blog.youkuaiyun.com/derrantcm
* Github: https://github.com/Wang-Jun-Chao
* Declaration: All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
while (scanner.hasNext()) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
int d = scanner.nextInt();
System.out.println(game24Points(a, b, c, d));
}
scanner.close();
}
/**
* 4个[1, 10]的能否通过加减乘除,得到数字为24
*
* @param a 第一个数字
* @param b 第二个数字
* @param c 第三个数字
* @param d 第四个数字
* @return true,可以组成24,false不可以组成24
*/
private static boolean game24Points(int a, int b, int c, int d) {
int[] arr = {a, b, c, d, '+', '-', '*', '/'};
boolean[] used = new boolean[arr.length];
LinkedList<Integer> list = new LinkedList<Integer>();
boolean[] rst = {false};
for (int i = 0; i < 4; i++) {
used[i] = true;
list.add(arr[i]);
to24(arr, used, 1, 0, list, rst);
if (rst[0]) {
return true;
}
list.removeLast();
used[i] = false;
}
return false;
}
/**
* 4个[1, 10]的能否通过加减乘除,得到数字为24
*
* @param arr 能够使用的操作数、操作符的数组
* @param used 已经使用的操作数、操作符标记数组
* @param numCnt 操作数的个数
* @param optCnt 操作符的个数
* @param list 求得的逆波兰式
* @param rst 保存中间结果,有满足24的就停止计算
*/
private static void to24(int[] arr, boolean[] used, int numCnt, int optCnt,
LinkedList<Integer> list, boolean[] rst) {
if (rst[0]) {
return;
}
if (numCnt > optCnt && numCnt + optCnt == 7) {
calInversePoland(list, rst);
}
else if (numCnt > optCnt) {
for (int i = 0; i < arr.length; i++) {
if (!used[i] || arr[i] < 0 || arr[i] > 10) {
if (arr[i] >= 0 && arr[i] <= 10) {
list.add(arr[i]);
numCnt++;
used[i] = true;
to24(arr, used, numCnt, optCnt, list, rst);
if (rst[0]) {
return;
}
list.removeLast();
numCnt--;
used[i] = false;
}
else if (numCnt + 1 > optCnt) {
list.add(arr[i]);
optCnt++;
used[i] = true;
to24(arr, used, numCnt, optCnt, list, rst);
if (rst[0]) {
return;
}
list.removeLast();
optCnt--;
used[i] = false;
}
}
}
}
}
/**
* 计算逆波兰式的值
*
* @param list 逆波兰式
* @param rst 用于保存计算结果
*/
private static void calInversePoland(LinkedList<Integer> list, boolean[] rst) {
LinkedList<Double> stack = new LinkedList<>();
for (int v : list) {
if (v >= 0 && v <= 10) {
stack.add((double)v);
} else {
double a = stack.removeLast();
double b = stack.removeLast();
double c = 0;
switch ((char) v) {
case '+':
c = a + b;
break;
case '-':
c = a - b;
break;
case '*':
c = a * b;
break;
case '/':
if (a == 0) {
return;
}
c = b / a;
break;
}
stack.add(c);
}
}
rst[0] = stack.getFirst() == 24.0;
}
}