C++ 学习笔记: 汉诺塔问题的迭代解法

启发

既然是非递归解法,那么运用的函数中就不能出现之间或间接地对自身的引用。迭代就是利用一个完整的解决算法,对每一步都利用该步数作为参数带入算法得出具体结果。所以要迭代,就必须分析汉诺塔移动过程中每一步体现的规律。


思路&部分代码

分解过程

每一步都可以分解为:
1.决定移动的盘号(假如对n个盘子编号,从小到大为1~n)
2.决定将盘子从哪移动到哪。

由此可知,要解决的问题就是:
1.如何确定每一步对应那个盘子;
2.如何确定盘子当前的位置和要移动的位置。

移动盘号

假设移动4个盘子,默认将盘子从1号移动到3号柱,2号柱作为临时存放点。过程如下(括号内代表移动的盘号):

1–2(1)
1–3(2)
2–3(1)
1–2(3)
3–1(1)
3–2(2)
1–2(1)
1–3(4)
2–3(1)
2–1(2)
3–1(1)
2–3(3)
1–2(1)
1–3(2)
2–3(1)

观察上面式子,可以知道:
1.总步骤数为15(也就是24 -1)
2.移动1号盘的步骤为:[1,3,5,7,9,11,13,15] ,移动2号盘的步骤为[2,6,10,14]; 移动3号盘的步骤为[4,12]; 移动4号盘的步骤为[8]
3.第一次移动1号盘在步骤1;第一次移动2号盘在步骤2;第一次移动3号盘在步骤4,第一次移动4号盘在步骤8。

间隔数

由此可看到, 1号盘的步骤数间隔为2(3-1,5-3,7-5), 2号的间隔数为4(6-2,10-6,14-10), 3号的间隔数为8(12-4).因此猜测每个盘间隔数和它的盘号有关:

盘号 间隔数
1 2=21
2 4=22
3 8=23
4 24=16

以此类推。

证明:
递归地分析移动n个盘子的过程可得:
n=1时,移动一次;
n=2时,移动1+1+1=3次(首尾两个1分别代表移动1号的步骤);
n=3时,先移动2个盘到临时点上,再移动3号,最后把1,2号移动到终点,因此:3+1+3 = 7次.
为n时,设 a n a_{n} an为总步数,则 a n a_{n} an=2 a n − 1 + 1 a_{n-1} + 1 an1+1
得出 a n = 2 n − 1 a_{n} = 2^{n} -1 an=2n1
图解如下:
移动过程
因此可以利用数学归纳法证明步骤间隔数和盘号的关系.
设移动总数为n的盘子们
其中1号:
因为移动了1号盘以后,下一步不可能再动1号,因此排除"存在任意连续的两步都移动1号"的假设.当移动了另外号码(假设a号)的盘子后(此时除1号呆的柱子,其他柱子上的盘子都比1号大),第三步一定会移动1号,因为移动之前a号下要么比a号大,要么没有盘子,又不可能再把a号移回去(无效操作),因此只能挪动1号.得出:一号的步骤间隔为2.
设k号盘的步骤间隔=2k 成立
k+1号:
总过程分解到(k+1)的层次,共有2(n-k-1) 个分叉.每个分叉都代表移动k个盘子的(2k-1 -1)步,因此间隔数:
a k + 1 = 2 k − 1 + 1 + 2 k − 1 + 1 = 2 k + 1 a_{k+1} = 2^{k}-1+1+2^{k}-1+1 = 2^{k+1} ak+1=2k1+

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值