题目连接:牛客网-算24点
自己些的递归,是通过全局控制变量,来控制递归结束的。
后来看了网友的代码,还有通过返回值来控制递归结束的。
在这里记录一下。
下面的代码里,
函数dfs是通过全局变量found来控制递归退出的。
函数dfs2是通过返回值来控制递归退出的。
package cn.line.nowcoder.huawei.hj67;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int[] pokers = new int[4];
for (int i = 0; i < 4; i++) {
pokers[i] = sc.nextInt();
}
// Poker24 p = new Poker24(pokers);
// p.dfs(0, 0);
// System.out.println(p.found);
Poker24 p2 = new Poker24(pokers);
System.out.println(p2.dfs2(0, 0));
}
sc.close();
}
}
class Poker24 {
private static final int USED = 1;
private static final int UNUSED = 0;
private final int[] pokers;
private int[] used;
private final int N = 4; // 4张牌,不是+-*/4则运算
private final int TARGET = 24;
public boolean found = false;
public Poker24(int[] pokers) {
this.pokers = pokers;
used = new int[N];
}
/**
* Controlled by Global Value
* @param current 当前计算值。初值0。
* @param n 当前使用的牌数。初值0
*/
public void dfs(int current, int n) {
if (n == N) {
if (current == TARGET) {
found = true;
return;
}
return;
}
for (int i = 0; i < N && !found; i++) {
if (used[i] == UNUSED) {
used[i] = USED;
dfs(current + pokers[i], n + 1);
if (found) return;
if (isLegal_Minus(current, pokers[i]))
dfs(current - pokers[i], n + 1);
if (found) return;
dfs(current * pokers[i], n + 1);
if (found) return;
if (isLegal_Devide(current, pokers[i]))
dfs(current / pokers[i], n + 1);
if (found) return;
used[i] = UNUSED;
}
}
}
/**
* Controlled by Return Value
*/
public boolean dfs2(int current, int n) {
if (n == N)
return current == TARGET;
for (int i = 0; i < N && !found; i++) {
if (used[i] == UNUSED) {
used[i] = USED;
if (dfs2(current + pokers[i], n + 1))
return true;
if (isLegal_Minus(current, pokers[i]) && dfs2(current - pokers[i], n + 1))
return true;
if (dfs2(current * pokers[i], n + 1))
return true;
if (isLegal_Devide(current, pokers[i]) && dfs2(current / pokers[i], n + 1))
return true;
used[i] = UNUSED;
}
}
return false;
}
private static boolean isLegal_Minus(int left, int right) {
return left >= right;
}
private static boolean isLegal_Devide(int left, int right) {
if (left == 0)
return false;
if (right > 5)
return false;
if (right == 1)
return true;
if (right == 2)
return (left == 2 || left == 4 || left == 6 || left == 8 || left == 10);
if (right == 3)
return (left == 3 || left == 6 || left == 9);
if (right == 4)
return (left == 4 || left == 8);
if (right == 5)
return (left == 5 || left == 10);
return true;
}
/**
* 剪枝
*/
private static boolean isLegal(char op, int left, int right) {
if (op == '-') {
return left >= right;
}
if (op == '/') { // 避免出现小数的情况
if (left == 0)
return false;
if (right > 5)
return false;
if (right == 1)
return true;
if (right == 2)
return (left == 2 || left == 4 || left == 6 || left == 8 || left == 10);
if (right == 3)
return (left == 3 || left == 6 || left == 9);
if (right == 4)
return (left == 4 || left == 8);
if (right == 5)
return (left == 5 || left == 10);
return true;
}
// +和*
return true;
}
}
因为一开始用的found变量做递归控制,而java又不支持参数的引用传递,所以新建了个Poker24类来做运算。
后来改为返回值控制,其实可以直接用一个静态函数就可以了。但是嫌麻烦,就只在这里记录一下,不做修改了。