24点游戏
给玩家4张牌,每张牌的面值都在1---13之间,允许其中有数值相同的牌。采用加、减、乘、除四则运算,允许中间运算存在小数,并且可以使用括号,但每张牌只能使用一次,尝试构造一个多项式,使其运算结果为24.
输入:n1,n2,n3,n4。
输出:若能得到运算结果为24,则输出一个对应的计算表达式。
输入:11,8,3,5
输出:(11-8)*(3+5) = 24
分析与解法
最直接的想法就是采用穷举法,因为运算符号只有4种,每个数字只能使用一次,所以通过穷举4个数所有可能的表达式,并分别计算出各表达式的值,就可以得到答案。那么如何穷举所有可能的表达式呢?
先不考虑使用括号,可以做出如下分析:
每个数只能使用一次,对4个整数进行全排列,总共有4!=4*3*2*1=24中排列。4个数的四则运算中总共需要3个运算符,同一运算符可以重复出现,那么对于每一个排列,总共可有4*4*4中表达式。因此在不考虑括号的情况下,总共可以得到4!*4*4*4=1536中表达式。
接下来再考虑加上括号后的情况,对于4个数而言,总共会有以下5种加括号的方式:
(A(B(CD)))、(A((BC)D))、((AB)(CD))、((A(BC))D)、(((AB)C)D)。
所以需要遍历的表达式数最多有4!*4*4*4*5=7680种。即使采用逆波兰表达式,其总数也不变。
通过上面的分析,得到了一种解24点的基本思路,即遍历运算符、数字和括号的所有排列组合形式,接下来,我们将更加细致地讨论这种解法的一个具体实现。
假设给定的4个数组成的集合为A={1,2,3,4},定义函数f(A)为对集合A中的元素进行所有可能的四则混合运算所得到的值。
首先从集合A中任意取出两个数,如取出1和2,A=A-{1,2},对取出来的数分别进行不同的四则运算,1+2=3,1-2=-1,1/2=0.5,1*2=2,将得到的结果再分别加入集合A,可得到B={3,3,4},C={-1,3,4},D={0.5,3,4},E={2,3,4}四个新的集合,那么f(A)= f(B)+f(C)+f(D)+f(E),通过以上的计算就达到了分而治之的目的,问题规模就从4个数降到了3个数,成了3个数的4个子问题之和。综上所述,可以得到递归解法如下:
将给定的4个数放入数组Array中,将其作为参数传入函数f中,伪代码如下所示:
具体代码如下所示:
运行效果图如下: