对“神奇24”游戏的一些思考

    “神奇24”游戏指的是,给出4个数abcd和+-*/(),求解一种运算方法使得,算式的结果为24。小时候曾经玩过这样的游戏,是在电脑上面的,现在想想看要实现起来也不难。

    最先想到的当然就是利用计算机的强大的计算算能力,去穷举每一个可能的表达式,判断其结果是不是24,将结果为24的表达式直接输出就可以了。其中就关系到表达式的生成和求解。

    表达式的求解方法,在数据结构里面讲了一种求解表达式的方法,后缀表达式的栈求解法。对于这个问题采用后缀表达式是最方便的,其优势在后面将会看到。后缀表达式的求解很简单:
后缀表示的算式是由左向右被扫描,对算式的每个元素施加如下的法则:
  1.若元素是一个变量或操作数,把它压入堆栈;
  2.若元素是一个操作符,则弹出堆栈顶部两个元素,完成操作,并将结果压入堆栈;
  2.整个表达式被扫描以后,表达式结果就保存在堆栈顶上。

    中缀表达式变后缀表达式的办法:
    这个算法归功于Dijkstra。从左到右扫描中缀表达式,随着扫描的进行,后缀表达式生成并输出,步骤如下:
      1.检查输入的下一个元素。
      2.若它是一个操作数,则输出它。
      3.若它是一个开括号(左括号),把它压入堆栈。
      4.若它是一个操作符,则
        若栈顶是一个开括号,把操作符压入堆栈。
        若它有比栈顶操作符更高的优先权(乘和除优先于加和减),则把此操作符压入堆栈,否则从堆栈探出操作符到输出,并重复步骤4。
      5.若它是一个闭括号(右括号),则弹出操作符到输出,直到遇上一个开括号,弹出作废此开括号。
      6.若还有输入,回到步骤1。
      7.若没有输入,则弹出所有剩余操作符到输出。

    为什么使用后缀表达式?这就要看看表达式的生成办法,如果用中缀表达式,难得就是表达式的生成,因为涉及到对括号的处理,仔细想想,就会知道其难度有多大。用后缀表达式则不需要处理括号的问题,而且借助后缀表达式,我们还可以分析所有的可能的表达式到底有多少个,并且都是什么形式,现分析如下:

    对于a b c d四个数,每一个数的位置首先是固定的,这是游戏规则要求的,这个就为我们的求解大大减低了难度,想想如果数的位置不固定,搜索的表达式的数目将是现在的4的阶乘倍。由中缀变到后缀,可以知道,其操作数的次序也是不变的,这一点从中缀表达式变后缀表达式的规则可以保证。另外重要的一点是,总可以保证在一个合法的后缀表达式中,任何一个操作符,其前面的操作符的个数(要包括此操作符),与其前面的操作数的个数总是有如下的关系:操作符个数<操作数个数。这一点至关重要,举几个例子:

    合法的后缀式:abcd-*+
    非法的后缀式:a+bcd-- (+前面有一个操作数1<1不成立)

    现在在看看如何构造这些合理的表达式吧,显然合理的形式只可能有如下的形式:
      1. ab*c*d*
      2. ab*cd**
      3. abc*d**
      4. abc**d*
      5. abcd***
    其中*代表加减乘除中的任意一个运算符,对于每一种形式就有4*4*4=64个表达式,总共有5种形式,则所有的表达式个数有64*5=320个,也就是说总共只用320个式子。

这样,我们就找到了所有的可能的式子的构造办法,构造完所有的式子后,再用后缀表达式的求解办法,求解每一个式子并判断是否等于24。

    剩下来要做的就是如何将后缀表达式变为中缀形式并输出了,这个并不难,参考后缀表达式的求解方法,就可以知道了,就是在遇到运算符的时候不求值,而直接生成一个字符串,压回堆栈即可。

    具体的实现现在还没有写出来,今天只能空口说说我想象中的实现办法,大家也不要笑话。

 

                                                                   作者:陈凯
                                                                   RockCarry工作室:http://rockcarry.126.com
                                                                   2005.1.7
                                                                   版权所有、不得转载

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值