汉诺塔问题的两种解法(6)

第六节 条件限定法——变量与过程

在开始编写程序之前,首先将此前已经完成的项目另存为“汉诺塔2”,并在汉诺塔2的基础上,编写新的程序。原有项目中需要保留的全局变量及过程如图30所示。

图30 需要保留的全局变量及过程

一、新增变量与过程完善

图30中部分过程需要加以完善,为此要先添加两个全局变量,如图31所示。

图31 添加两个全局变量

全局变量“最后移动项”用来保存上一次移动的数字,“步数”用来保存已经移动的步数。

需要完善的过程有两个——移动1过程及初始化过程,如图32所示,在这两个过程中对新添加的全局变量进行设置,并在初始化过程中增加对显示结果过程的调用。

图32 完善过程,对新添加的全局变量进行设置

针对每一次移动,记录被移动的数字——最后移动项,以及移动的步数。在即将编写的程序中,最后移动项用来确定下一次移动的出发点。

二、创建新过程

(1)有返回值的过程——是偶数

根据第五节的结论c,在移动数字1时,如果塔高为奇数,则移动到落脚点,否则,移动到相对缓冲区,因此定义一个有返回值的过程——是偶数,以便根据塔高决定数字“1”的落脚点,代码如图33所示。

图33 有返回值过程——是偶数

(2)有返回值的过程——任务完成

如图34所示,当左侧的数字全部移动到右侧时,该过程的返回值为真。

图34 有返回值的过程——任务完成

(3)有返回值的过程——塔高

根据第五节的结论d计算塔高。在计算塔高时,需要留心一种可能存在的情况。举例说明,假设实际塔高为5,那么它可能是(1,2,3,4,5),但也可能是(1,2,3,7,8),我们需要识别出这两种情况,前者的塔高=5,而后者的塔高=3。实际上我们要求的塔高必须是列表中最小的、且连续差值为1的数字的个数,因此,一旦遇到两个连续项的差不等于1,则塔高的值就已经确定了。塔高过程的代码如图35所示,一旦两个连续项的差值≠1,则设索引值为空表最大值,立即退出循环,返回计算结果。

图35 有返回值过程——塔高

(4)有返回值的过程——出发点

根据第五节中给出的证明:每一次移动的出发点都是唯一的。如果不是第一次移动,则可以利用全局变量最后移动项,排除掉三分之一的选项(上一次移动的落脚点),然后在剩余的三分之二选项中,选择首项值较小者为出发点。(在上一节我们已经证明:如果选择首项值较大者为出发点,那么它将无法找到符合游戏规则的落脚点。)根据这一结论编写一个有返回值的过程——出发点,代码如图36所示。

图36 有返回值的过程——出发点

(5)有返回值的过程——落脚点

根据第五节的结论b,当出发点的数字≠1时,落脚点是唯一的。我们来定义过程,求出这个唯一的落脚点,代码如图37所示。

图37 有返回值的过程——落脚点

(6)有返回值的过程——塔尖落脚点

上面已经求出了被移动数字≠1时的落脚点,现在来解决被移动数字=1时的落脚点问题。根据第五节的结论c,“塔”的落脚点是唯一的,但塔尖的“1”落脚点不唯一,它与塔高有关,当塔高为奇数时,塔与塔尖(数字1)的落脚点相同,反之则不同。根据结论c,塔落脚点的首项值与出发点的塔底值相差1,据此确定塔尖的落脚点,相应的过程代码如图38所示。在判断S、T、B是否为出发点时,程序中使用了“S1=1”这样的条件,它等同于“S=出发点”这样的条件,但是前者是数值之间的比较,而后者是列表之间的比较,后者会消耗更多的计算力。

图38 有返回值的过程——塔尖落脚点

我们依据第五节中的4个条件及4个结论,确定了每一次移动的出发点及落脚点。如上所述,其实每一步移动都可以在前一步的基础上,确定唯一的移动路径,这样的结果得益于对物理世界中移动过程的观察、分析及归纳。运用人类自身的智能,可以极大地提高机器解决问题的效率,而这正是我们希望获得的能力。

有了上面的过程,我们就有了每次移动的出发点及落脚点,因此余下的事情就简单了。

== 未完待续 ==

(0)

相关推荐

  • 不要让爱变成了恨

    即使不爱了也不要互相伤害,不爱是两个人的事,但互相伤害就是两家人的事.不要因为不爱,就变成了恨,相爱是两个人的幸福.宠爱的出发点是爱,落脚点却是恨:嫉妒的出发点是进,落脚点却是退:梦幻的出发点是绚(烂 ...

  • 出发点与落脚点

    宠爱的出发点是爱,落脚点却是恨: 嫉妒的出发点是进,落脚点却是退: 梦幻的出发点是绚,落脚点却是空: 贪婪的出发点是盈,落脚点却是亏.

  • 落脚点

    宠爱的出发点是爱,落脚点却是恨: 嫉妒的出发点是进,落脚点却是退: 梦幻的出发点是炫,落脚点却是空: 贪婪的出发点是盈,落脚点却是亏.

  • 汉诺塔问题的两种解法(1)

    汉诺塔是一种益智玩具,源自古老的印度.如图1.图2及图3所示,有三根柱子,若干个大小不等的圆盘按顺序依次叠落在起点(左侧)的柱子上,通过多次移动后,全部圆盘要叠落在终点(右侧)的柱子上.移动必需遵守两 ...

  • 汉诺塔问题的两种解法(2)

    第二节 关键性结论 通过反复实践与观察,我们发现了解决汉诺塔问题的思路.无论圆盘的数量有多少,我们都可以把它们当作2个盘子来处理.假设共有N个圆盘,我们把它们想象为两个圆盘,其中一个圆盘是整个塔的塔底 ...

  • 汉诺塔问题的两种解法(3)

    第三节 汉诺塔的递归解法--移动两个盘子 一.用户界面 在App Inventor中创建一个项目,命名为汉诺塔,用户界面在手机中的样子如图11所示,在AppInventor设计视图中,为项目添加组件, ...

  • 汉诺塔问题的两种解法(4)

    第四节 汉诺塔问题的递归解法--移动所有盘子 上一节我们实现了连续移动两个盘子(数字),现在我们发挥一点儿想象力,将上一节的两个盘子当作一个盘子来处理,从而得出移动3个盘子的过程,代码如图22所示. ...

  • 汉诺塔问题的两种解法(5)

    第五节 条件限定法--限定条件 限定条件法不关注移动过程的整体规律,而着眼于具体的移动路径(规定每一步移动的出发点及落脚点),对每一种可能的移动路径设置限定条件,通过对限制条件的设置及调整,逐渐找到最 ...

  • 汉诺塔问题的两种解法(7)

    第七节 条件限定法--演示移动过程 上一节完善了2个已有过程,并新增了6个有返回值的过程,完成了对出发点.落脚点的选择,有了这些结果,本节可以收获成果了. 一.两个无返回值过程 (1)不连续移动 出发 ...

  • 汉诺塔问题的两种解法(8)

    第八节 求解过程小结 我们已经完成了对数字(盘子)的移动,并成功地演示了数字的移动过程.阅读并理解前面几节中的程序并不难,就这个例子而言,难的不是程序,而是编写程序之前对移动规律的归纳与整理,这也正是 ...

  • 科目余额表,只取最明细一级数据?Power Query和Power Pivot两种解法!

    小勤:下面这个表里是从财务系统里导出来的科目表,怎么能只保留本币里的最底层明细数据?最终本币列结果如右侧所示: 大海:能通过判断下一行中的科目编码是否包含本行科目编码来判断当前行是否为非明细行吗? 小 ...

  • 分享一道圆,两种解法,一种倍长中线余弦定...

    分享一道圆,两种解法,一种倍长中线余弦定...