小朋友3年级的数学题:1 2 3 4 5 每个数字之间填上符号,使最后计算结果等于20。要找到一个答案就很容易,但小朋友要比试谁找到的答案多,这就有意思了。干脆写个程序来穷举所有的例子。
这种问题,第一个就要想到使用栈,因为数字排列是有顺序的。按1,2,3,4,5的顺序依次push到栈中,每次push一个新数字进去的时候,可以有五个选择:
1、什么都不做
2-5、pop两个数字,分别做加、减、乘、除,然后把结果push进栈
因此尝试每种选择,进行递推的处理。每试过一种选择之后,都要把现场还原——把放进栈中的数字取出来,把取出来的数字放回去。最后就是栈外没有数字,栈中只有一个数字,如果这个数字是20,那么就有一个解了。
在这个过程中,注意要记录每一步生成的算式,再处理一下括号的问题,就完成了。
import Util.OperateType;
import Util.Polynomial;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class FillOperator {
private static Stack<Polynomial> restPolynomial = new Stack<Polynomial>();
private static Stack<Polynomial> runStack = new Stack<Polynomial>();
private static OperateType[] opes = new OperateType[]{OperateType.OPE_ADD,
OperateType.OPE_SUBTRACT,
OperateType.OPE_MUTIPLY,
OperateType.OPE_DIVIDE};
private static int targetValue;
private static List<String> resultList = new ArrayList<String>();
public static void main(String[] args){
targetValue = 20;
restPolynomial.push(new Polynomial(5));
restPolynomial.push(new Polynomial(4));
restPolynomial.push(new Polynomial(3));
restPolynomial.push(new Polynomial(2));
restPolynomial.push(new Polynomial(1));
round();
for (String desc : resultList){
System.out.println(desc);
}
}
private static void round(){
if ((restPolynomial.isEmpty()) && (1 == runStack.size())){
if (targetValue == runStack.get(0).value){
if (!resultList.contains(runStack.get(0).desc)){
resultList.add(runStack.get(0).desc);
}
}
return;
}
if (!restPolynomial.isEmpty()){
Polynomial basePolynomial = restPolynomial.pop();
runStack.push(basePolynomial);
round();
runStack.pop();
restPolynomial.push(basePolynomial);
}
if (runStack.size() >= 2){
Polynomial b = runStack.pop();
Polynomial a = runStack.pop();
for (OperateType opeType : opes){
Polynomial mergedPolynomial = a.merge(b, opeType);
if (null != mergedPolynomial){
runStack.push(mergedPolynomial);
round();
runStack.pop();
}
}
runStack.push(a);
runStack.push(b);
}
}
}
package Util;
public enum OperateType {
OPE_ADD,
OPE_SUBTRACT,
OPE_MUTIPLY,
OPE_DIVIDE,
OPE_NONE;
public static int compareOpearteType(OperateType a, OperateType b){
if (((OPE_MUTIPLY == a) || (OPE_DIVIDE == a)) && ((OPE_ADD == b) || (OPE_SUBTRACT == b))){
return 10; // 10表示 a 更高级
}
if (((OPE_MUTIPLY == b) || (OPE_DIVIDE == b)) && ((OPE_ADD == a) || (OPE_SUBTRACT == a))){
return -10; // -10表示 b 更高级
}
return 0; // 0 表示 a,b同级
}
}
package Util;
public class Polynomial {
public int value;
public String desc;
public OperateType operateType;
public Polynomial(int value){
this.value = value;
this.desc = String.valueOf(value);
this.operateType = OperateType.OPE_NONE;
}
public Polynomial merge(Polynomial target, OperateType opeType) {
Polynomial mergedPolynomial = null;
switch (opeType) {
case OPE_ADD:
mergedPolynomial = new Polynomial(this.value + target.value);
mergedPolynomial.desc = mergeDesc(this, target, opeType);
mergedPolynomial.operateType = OperateType.OPE_ADD;
break;
case OPE_SUBTRACT:
if (this.value >= target.value) {
mergedPolynomial = new Polynomial(this.value - target.value);
mergedPolynomial.desc = mergeDesc(this, target, opeType);
mergedPolynomial.operateType = OperateType.OPE_SUBTRACT;
}
break;
case OPE_MUTIPLY:
mergedPolynomial = new Polynomial(this.value * target.value);
mergedPolynomial.desc = mergeDesc(this, target, opeType);
mergedPolynomial.operateType = OperateType.OPE_MUTIPLY;
break;
case OPE_DIVIDE:
if ((target.value != 0) && (0 == (this.value % target.value))) {
mergedPolynomial = new Polynomial(this.value / target.value);
mergedPolynomial.desc = mergeDesc(this, target, opeType);
mergedPolynomial.operateType = OperateType.OPE_DIVIDE;
}
break;
default:
break;
}
return mergedPolynomial;
}
private String mergeDesc(Polynomial a, Polynomial b, OperateType opeType){
String left, right;
if (OperateType.OPE_NONE == a.operateType){
left = a.desc;
}else{
if (10 == OperateType.compareOpearteType(opeType, a.operateType)){
left = String.format("(%s)", a.desc);
}else{
left = a.desc;
}
}
if (OperateType.OPE_NONE == b.operateType){
right = b.desc;
}else{
if ((OperateType.OPE_SUBTRACT == opeType) || (OperateType.OPE_DIVIDE == opeType)){
right = String.format("(%s)", b.desc);
}else if (10 == OperateType.compareOpearteType(opeType, b.operateType)){
right = String.format("(%s)", b.desc);
}else {
right = b.desc;
}
}
switch (opeType) {
case OPE_ADD:
return String.format("%s + %s", left, right);
case OPE_SUBTRACT:
return String.format("%s - %s", left, right);
case OPE_MUTIPLY:
return String.format("%s x %s", left, right);
case OPE_DIVIDE:
return String.format("%s / %s", left, right);
default:
return "";
}
}
}