计算24点算法基本原理是穷举4个整数所有可能的表达式,然后对表达式求值。表达式的定义: expression = (expression|number) operator (expression|number)
因为能使用的4种运算符 + - * / 都是2元运算符,所以本文中只考虑2元运算符。2元运算符接收两个参数,输出计算结果,输出的结果参与后续的计算。由上所述,构造所有可能的表达式的算法如下:
(1) 将4个整数放入数组中
(2) 在数组中取两个数字的排列,共有 P(4,2) 种排列。对每一个排列,
(2.1) 对 + - * / 每一个运算符,
(2.1.1) 根据此排列的两个数字和运算符,计算结果
(2.1.2) 改表数组:将此排列的两个数字从数组中去除掉,将 2.1.1 计算的结果放入数组中
(2.1.3) 对新的数组,重复步骤 2
(2.1.4) 恢复数组:将此排列的两个数字加入数组中,将 2.1.1 计算的结果从数组中去除掉可见这是一个递归过程。步骤 2 就是递归函数。当数组中只剩下一个数字的时候,这就是表达式的最终结果,此时递归结束。在程序中,一定要注意递归的现场保护和恢复,也就是递归调用之前与之后,现场状态应该保持一致。在上述算法中,递归现场就是指数组,2.1.2 改变数组以进行下一层递归调用,2.1.3 则恢复数组,以确保当前递归调用获得下一个正确的排列。括号 () 的作用只是改变运算符的优先级,也就是运算符的计算顺序。所以在以上算法中,无需考虑括号。括号只是在输出时需加以考虑。对象设计如下:
类 类含有的变量 类含有的方法 说明Number double value String toString() 这样可以清晰地表达出 expression 的递归定义Expression extends Number Number left Number right char operator String toString() Calculator Number[] numbers Expression[] expressions
add() clear() //操作 numbers
calculate()
Permutor permutor() java 程序的主类,实现算法Permutor int i,j boolean next() 排列生成器,类似 iterator,从一个指定的数组中生成2个元素的排列
因为能使用的4种运算符 + - * / 都是2元运算符,所以本文中只考虑2元运算符。2元运算符接收两个参数,输出计算结果,输出的结果参与后续的计算。由上所述,构造所有可能的表达式的算法如下:
(1) 将4个整数放入数组中
(2) 在数组中取两个数字的排列,共有 P(4,2) 种排列。对每一个排列,
(2.1) 对 + - * / 每一个运算符,
(2.1.1) 根据此排列的两个数字和运算符,计算结果
(2.1.2) 改表数组:将此排列的两个数字从数组中去除掉,将 2.1.1 计算的结果放入数组中
(2.1.3) 对新的数组,重复步骤 2
(2.1.4) 恢复数组:将此排列的两个数字加入数组中,将 2.1.1 计算的结果从数组中去除掉可见这是一个递归过程。步骤 2 就是递归函数。当数组中只剩下一个数字的时候,这就是表达式的最终结果,此时递归结束。在程序中,一定要注意递归的现场保护和恢复,也就是递归调用之前与之后,现场状态应该保持一致。在上述算法中,递归现场就是指数组,2.1.2 改变数组以进行下一层递归调用,2.1.3 则恢复数组,以确保当前递归调用获得下一个正确的排列。括号 () 的作用只是改变运算符的优先级,也就是运算符的计算顺序。所以在以上算法中,无需考虑括号。括号只是在输出时需加以考虑。对象设计如下:
类 类含有的变量 类含有的方法 说明Number double value String toString() 这样可以清晰地表达出 expression 的递归定义Expression extends Number Number left Number right char operator String toString() Calculator Number[] numbers Expression[] expressions
add() clear() //操作 numbers
calculate()
Permutor permutor() java 程序的主类,实现算法Permutor int i,j boolean next() 排列生成器,类似 iterator,从一个指定的数组中生成2个元素的排列
解决方案 »
- 读txt文件的问题
- 问一个JAVA范型方面的问题
- 遇到个小问题 进来解答下
- 测试BufferedInputStream的mark()和reset()方法,提交文件时会出现Resetting to invalid mark
- 如何读取一个远程文件,比如说,\\192.168.2.4\d:\test\test.txt
- 希望大家能教我一个怎么把一个image的图形信息显示在applet上的方法
- 帮我编一个简单的加密程序?
- 请大侠看看这段代码有什么错误?
- 布局管理器有什么用?
- 文件操作问题
- 输入一句英文的句子,如何一个一个单词地输出?
- 判断一个字符串是不是另一个字符串的字串,如果是显示字串开始出现的位置.这样写怎么不行啊?
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
class Detail {
int value;
String strValue; public Detail() {
} public Detail(int value) {
this.value = value;
this.strValue = String.valueOf(value);
}
}
public class C24 {
/**
* @param args
*/
public static void main(String[] args) {
C24 c24 = new C24(); c24.C24p();
} void C24p() {
int[] srcCards = generateCards();
boolean hasAnswer = false; // int[] srcCards ={4,1,2,10};
try {
List<int[]> all = allPermutation(srcCards);
List<Detail> results = new ArrayList<Detail>(); for (int[] cards : all) {
List<Detail> oneCase = calEachCase(cards);
results.addAll(oneCase);
} for (Detail detail : results) {
if (detail.value == 24) {
hasAnswer = true;
System.out.println(detail.strValue);
}
}
} catch (Exception e) {
e.printStackTrace();
System.err.println(Arrays.toString(srcCards));
} if (!hasAnswer) {
System.out.println("No Answer");
System.out.println(Arrays.toString(srcCards));
}
} int[] generateCards() {
int[] rtn = new int[4];
Random rand = new Random(); for (int i = 0; i < rtn.length; i++) {
rtn[i] = rand.nextInt(10) + 1;
} return rtn;
} List<int[]> allPermutation(int[] cards) {
List<int[]> rtn = new ArrayList<int[]>();
int length = cards.length; if (length == 1) {
rtn.add(cards); return rtn;
} for (int i = 0; i < length; i++) {
int card = cards[i];
int[] leftCards = removeOne(cards, i);
List<int[]> newRtn = allPermutation(leftCards); for (int[] js : newRtn) {
int[] newCards = new int[length];
newCards[0] = card;
System.arraycopy(js, 0, newCards, 1, length - 1);
rtn.add(newCards);
}
} return rtn;
} int[] removeOne(int[] cards, int index) {
int[] newCards = new int[cards.length - 1];
int j = 0; for (int i = 0; i < cards.length; i++) {
if (index != i) {
newCards[j] = cards[i];
j++;
}
} return newCards;
} List<Detail> calEachCase(int[] cards) {
List<Detail> list = new ArrayList<Detail>();
int x = cards[0];
int y = cards[1];
int z = cards[2];
int u = cards[3];
List<Detail> listA = cal(new Detail(x), new Detail(y));
List<Detail> listB = cal(new Detail(z), new Detail(u));
list.addAll(cal(listA, listB)); List<Detail> list1 = cal(new Detail(x), new Detail(y));
List<Detail> list2 = cal(list1, new Detail(z));
List<Detail> list3 = cal(list2, new Detail(u));
list.addAll(list3); return list;
} List<Detail> cal(Detail detail1, Detail detail2) {
int x = detail1.value;
int y = detail2.value;
String strX = detail1.strValue;
String strY = detail2.strValue;
List<Detail> rtnList = new ArrayList<Detail>();
Detail detail = null;
detail = new Detail();
detail.value = x + y;
detail.strValue = "(" + strX + "+" + strY + ")";
rtnList.add(detail);
detail = new Detail();
detail.value = x - y;
detail.strValue = "(" + strX + "-" + strY + ")";
rtnList.add(detail);
detail = new Detail();
detail.value = x * y;
detail.strValue = "(" + strX + "*" + strY + ")";
rtnList.add(detail); if ((y != 0) && ((x % y) == 0)) {
detail = new Detail();
detail.value = x / y;
detail.strValue = "(" + strX + "/" + strY + ")";
rtnList.add(detail);
} return rtnList;
} List<Detail> cal(List<Detail> list, Detail detail) {
List<Detail> rtnList = new ArrayList<Detail>(); for (Detail det : list) {
rtnList.addAll(cal(det, detail));
} return rtnList;
} List<Detail> cal(List<Detail> list1, List<Detail> list2) {
List<Detail> rtnList = new ArrayList<Detail>(); for (Detail detail1 : list1) {
for (Detail detail2 : list2) {
rtnList.addAll(cal(detail1, detail2));
}
} return rtnList;
}
}引用别人的,可以参考下。