前言
经过前期的数据结构和算法学习,开始以OD机考题作为练习题,继续加强下熟练程度。
描述
给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算
此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。
输入描述:
读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。
输出描述:
对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false
示例1
输入:
7 2 1 10
输出:
true
实现原理与步骤
1.从4个中随意选择2个数字,按加减乘除4种方式计算出结果,每个结果再与剩下的2个数字合并组成新数组重新执行流程计算。
2.重复上述计算方式直接数组中仅存一个数字,判断该数字是否为24.如果是则返回ture,如果不是则剩下的数组中删除最后个加入的元素。
实现代码
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int[] arr=new int[4];
int i=0;
while(in.hasNextInt()){
arr[i++]=in.nextInt();
}
boolean res=canReach24(arr);
System.out.println(res);
}
// 检查是否可以通过四个数字得到24
public static boolean canReach24(int[] nums) {
List<Double> numbers = new ArrayList<>();
for (int num : nums) {
numbers.add((double) num);
}
return dfs(numbers);
}
// 深度优先搜索解决问题
private static boolean dfs(List<Double> numbers) {
if (numbers.size() == 1) {
return Math.abs(numbers.get(0) - 24) ==0; // 检查是否接近24
}
// 枚举所有两两组合
for (int i = 0; i < numbers.size(); i++) {
for (int j = 0; j < numbers.size(); j++) {
if (i != j) {
List<Double> nextNumbers = new ArrayList<>();
for (int k = 0; k < numbers.size(); k++) {
if (k != i && k != j) {
nextNumbers.add(numbers.get(k));
}
}
// 枚举所有运算符组合
for (double result : computeResults(numbers.get(i), numbers.get(j))) {
nextNumbers.add(result);
if (dfs(nextNumbers)) {
return true;
}
nextNumbers.remove(nextNumbers.size() - 1);
}
}
}
}
return false;
}
// 计算两个数字的所有可能运算结果
private static List<Double> computeResults(double a, double b) {
List<Double> results = new ArrayList<>();
results.add(a + b);
results.add(a - b);
results.add(b - a);
results.add(a * b);
if (b != 0) {
results.add(a / b);
}
if (a != 0) {
results.add(b / a);
}
return results;
}
}