汉诺塔问题
汉诺塔(tower of hanoil)问题是源于印度一个古老传说。是递归应用中非常经典的一种表现。
问题大致描述如下
假设有A、B、C三个木桩和n个大小均不相同的盘子,从小到大编号依次为1、2、3 … n,编号越大直径越大。起初,这些盘子均被套在木桩A上,现在希望将A木桩上的盘子借助B木桩当桥梁,以最少次数全部移到C木桩上。在移动时还需遵循以下规则:
- 每次只能移动一个盘子,而且只能从最上面的盘子开始移动。
- 盘子可以从任意一个木桩移动到另一个木桩。
- 直径较小的盘子永远只能至于直径较大的盘子之上.
先分析只有一个盘子的情况,根据这些盘子移动步骤,带来的现象找出汉诺塔问题的规律。
当 n = 1时
移动次数:
直接将盘子从A木桩移动到C木桩
当 n = 2时
移动次数:
①将1号盘子从A木桩移动到B木桩
②将2号盘子从A木桩移动到C木桩
③将1号盘子从B木桩移动到C木桩
当 n = 3时
移动次数:
①将1号盘子从A木桩移动到C木桩
②将2号盘子从A木桩移动到B木桩
③将1号盘子从C木桩移动到B木桩
④将3号盘子从A木桩移动到C木桩
⑤将1号盘子从B木桩移动到A木桩
⑥将2号盘子从B木桩移动到C木桩
⑦将1号盘子从A木桩移动到C木桩
当n的值不大时,我们可以用图解解决问题,但是当n的值较大时,再用图解问题就会变得困难。从这三种情况可以大致发现汉诺塔移动的规律,归纳为3个步骤
1、将n-1个盘子,从木桩A移动到木桩B。
2、将第n个最大盘子,从木桩A移动到木桩C。
3、将n-1个盘子,从木桩B移动到木桩C。
用递归方法描述汉诺塔的算法函数
void hanoi(int n, const char *p1, const char *p2, const char *p3)
{
if(n==1) //递归出口
cout<<"盘子从"<< p1 <<"移到"<< p3;
else
{
haoni(n-1,p1,p3,p2);
cout<<"盘子从"<< p1 <<"移动到"<< p3;
haoni(n-1,p2,p1,p3);
}
}
移动n个盘子需要的最少移动次数
int hanoi(int n)
{
if (n == 1)
return 1;
else
return 2 * hanoi(n - 1)+1;
}