西西河

主题:【原创】将24进行到底 -- 泰让

共:💬28 🌺15 新:
全看分页树展 · 主题 跟帖
家园 【注释之1】总体原理

首先说一下总体上的思路。其实很多朋友已经看出,如果想穷尽4张牌的所有可能的计算,需要找到一个排列方法,能够不遗漏的列举每个算式。运算的数好办,因为它们都只严格的出现1次,问题是对于运算符,简单的插入三个运算符在四个数的空隙中是不行的,因为要是我们加入括号改变运算顺序,其结果也就不同了。但是如果我们要考虑所有插入括号的方式,虽然仍然是可行,但问题就变的相当复杂了。

好在算术表达式不仅仅有常见的中缀法,还有后缀法,或者称为逆波兰法(RPN)。这种方法先写两个参加运算的部分(可以是数,或者小一极的表达式)。简单的说就是原本用1+2来表示的运算,写成rpn就是1 2+,再比如说我们用中缀表示的算式(4-4/7)*7用后缀可以表示成4 4 7 / - 7 *。注意我们这里假定运算数间有可分辨的分隔,这样4 ,4 ,7三个数不至于同四百四十七混淆。

这样表示有什么好处?第一:这么写以后可以不用括号表达所有算式,而如果我们把一个数看作一位,一个运算符也看作1位的话,这个表达式长度总是7位。第二:这样写后计算过程简单。对于有括号的四则运算的解析和运算其实是相当复杂的问题,编译原理中会有一章专门讲这个问题。对于RPN计算就简单很多,我们可以很机械的执行以下步骤:遇到运算数则压栈,如果遇到运算符则将栈顶两运算数进行相应操作。最后如果RPN没有语法错误的话,栈应该只剩下一个数,就是结果。

回到原本的问题,我们现在要做的就是生成所有可能的RPN,然后运算之,检查它是否结果是24。如果我们用1到4代表输入的4张牌点,5到8代表加减乘除四种运算的话,问题就变成了我们如何生成一个7个数的组合,满足以下条件:

1:一到四出现1次且仅出现一次

2:五到八可以重复出现,也可以不出现

3:在任何时候,一到四出现的总数,比五到八出现的次数多(这一条是保证生成的是合乎语法的RPN)

生成了一个组合后,再用上面说的计算方法来算出结果,检查下是否是目标就可以了。当然注意运算过程中别发生除零的错误。

全看分页树展 · 主题 跟帖


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河