比如 2,4,6,Q(12) 这4个数,可能的答案有:
2 + 4 + 6 + 12 = 24
4 × 6 ÷ 2 + 12 = 24
12 ÷ 4 × (6 + 2) = 24
但要过滤掉雷同的答案,比如:
(12 + 6) + (4 + 2) = 24 (用交换律、结合律给出的不同答案是雷同的)
12 + 6 ÷ 2 * 4 = 24 (加减法或乘除法顺序颠倒)
还有无用的数怎么组合都是雷同的,比如:4,5,5,6 这四个数,以下两个答案只能算一个:
4 * 6 + 5 - 5 = 24
4 * 6 * 5 / 5 = 24
感觉挺复杂的,一时想不到一个好办法来处理。
补充
搜到一个算24点的页面:http://www.dffyw.com/tool/24.htm ,但是它会把所有的雷同情况都列出来,比如输入 2,4,6,12 这4个数,会有394种答案,其实不同的答案并没多少。
再补充
我自己穷举了下,2,4,6,12应该有以下10种不雷同的解答:
12+(6+(3*2))=24
(6*(3*2))-12=24
3*(12-(6-2))=24
6+(12*(3/2))=24
(2*(12+3))-6=24
12+(3*(6-2))=24
(3*(12-2))-6=24
6+(2*(12-3))=24
(12/2)+(6*3)=24
(12*3)-(6*2)=24
应该没有更多的吧。
再补充
带1和2的情况要特殊考虑,例如:A、J、K、Q
12*((13*1)-11)=24
12*((13/1)-11)=24
用1来做乘除法时,属于雷同的解答。又例如:2、2、3、3
(2+2)*(3+3)=24
2*2*(3+3)=24
2+2
和2*2
应被视为雷同的步骤。
题主所说的“雷同”,可以理解为“用字母替换数字后得到的代数式等价”。也就是说,当得到一个24点算式后,把它用代数变换导出的所有算式均不视为新发现。比如:
因此得到算法:
构造所有的数字算式
筛选出计算结果是24的算式
将算式中的数字用符号替换,并对得到的代数式做等价判断,每个等价类选出一个代表
输出代表代数式对应的数字算式
这种穷举构造法的复杂度至少是指数级的,因此不适用于数字较多的情况。
Mathematica 实现
Mathematica 的符号代数功能非常适合处理这类题目。
用符号
add
、sub
、mul
、div
分别对应加减乘除四则运算,构建二叉树代表算式。Groupings
函数生成了所有可能的表达式二叉树。Select
筛选出计算结果符合要求的。Union
负责除去雷同的算式。它的SameTest
选项计算两个代数式的差化简后是否为0。注意这里通过把数字转为字符进行“符号化”了,而且对数字1、2进行了特殊处理(specifics
)。最后
Map
负责把每个算式转成字符串输出。测试: