/*
n阶Hanoi塔问题:
假设有3个分别命名为x、y、z的塔座,在塔座x上插有n个直径大小各不相同、依小到大编号为1,2,...,n的圆盘。
现在要求将x轴上的n个圆盘移至塔座z上并仍然按同样顺序叠排,圆盘移动时必须遵循下列规则:
(1)每次只能移动一个圆盘
(2)圆盘可以插在x、y和z中的任一塔座上
(3)任何时候都不能将一个较大的圆盘压在较小的圆盘之上。
如何实现移动圆盘的操作呢?当n=1时,问题比较简单,只要将编号为1的圆盘从塔座x直接移动到塔座z上即可;
当n>1时,需要利用塔座y作为辅助塔座,若能设法将压在编号为n的圆盘之上的n-1个圆盘从塔座x移动到塔座y上,则可先将编号为n的圆盘从塔座x移到塔座z上。
而如何将n-1个圆盘从一个塔座移到另一个塔座的问题是一个和原问题具有相同特征属性的问题,只是问题的规模小1,因此可以用同样的方法求解。
*/
#include <iostream>
int c = 0; //用于计数移动的次数
void hanoi(int n, char x, char y, char z) {
if (n == 1) {
//当只有一个圆盘的时候直接把圆盘从x塔座移动到z塔座
printf("%i. Move disk %i from %c to %c\n", ++c, n, x, z);
}
else {
//当n>1时,把编号为1到n-1的圆盘移动到y塔座,z作为辅助塔座
hanoi(n - 1, x, z, y);
//然后将编号为n的圆盘从x塔座移动到z塔座
printf("%i. Move disk %i from %c to %c\n", ++c, n, x, z);
//然后将编号从1到n-1的圆盘从y塔座移动到z塔座,x作为辅助塔座
hanoi(n - 1, y, x, z);
}
}
int main()
{
hanoi(4, 'x', 'y', 'z');
/*
我们也可以从程序中看到一个规律:
当n=1时,只有1次移动;
当n>1时,最后一个编号为n的圆盘只移动1次,而编号为n-1的圆盘要经历2次移动。
通过递归的思想可以概括理解为第n个盘移动一次,第n-1个盘就要移动2次,第n-2个盘就要移动4次...,第1个盘就要移动2^(n-1)。
由于最后的圆盘次序依旧是从1到n的顺序从上到下叠起来的,所以只需考虑第1个圆盘的移动次数再加上第n个圆盘的移动次数即可
于是得出总结:总的移动次数为2^(n-1)+1
*/
}
运行结果:
1. Move disk 1 from x to y
2. Move disk 2 from x to z
3. Move disk 1 from y to z
4. Move disk 3 from x to y
5. Move disk 1 from z to x
6. Move disk 2 from z to y
7. Move disk 1 from x to y
8. Move disk 4 from x to z
9. Move disk 1 from y to z
10. Move disk 2 from y to x
11. Move disk 1 from z to x
12. Move disk 3 from y to z
13. Move disk 1 from x to y
14. Move disk 2 from x to z
15. Move disk 1 from y to z