Hanio 算法——分治策略
Hanio 问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
问题描述
今有 A、B、C 三个塔座,最初在塔座A上有 n 个圆盘,其中这n个圆盘的堆叠顺序是按照大小由大到小、从下到上进行排序。先将 A 上的n个圆盘移动到 C 上。
移动规则:
- 每次只移动一个圆盘
- 不允许将大圆盘放在小圆盘上
- 在满足1、2的情况下,可将圆盘任意移动到A、B、C上。
设计思路
我们先声明Hanio的算法函数,并暂时将此函数看做是一个黑箱。
// 输入:塔盘A、 塔盘B、 圆盘个数n
// 功能:将塔盘A中n个元素按原始顺序移动到塔盘B上
void Hanio(A,B,n);
这是一道典型的 分治策略 算法:
我们先回顾一下 分治策略 的 设计思想 :
- 将原问题划分或归结为规模较小的子问题
- 递归或迭代求解每个子问题
- 将子问题的解综合得到原问题的解
在划分为子问题的过程中一般有 对半划分 和 等差划分 方式。我们再看Hanio这个问题,对半划分将n个问题划分为2个 n/2 子问题不合适,而在每次递归或迭代中将n个问题划分成 n - 1 个和 1 个子问题则可巧妙地设计出Hanio问题的解决途径。
如图,在初始状态下,我们将 塔盘A 中的 n 个圆盘化为 n - 1 和 1 两个部分,最底层的圆盘为 1 个子问题,而上面的 n - 1 个圆盘构成 n - 1 个子问题。