引言
“枪炮分长短,佼人有深浅”
在第一篇递归方法论的文章中,我们讨论了如何将问题高效地进行分解,以便于提高程序的计算效率,上一篇文章的地址如下:
http://blog.csdn.net/huzhiyuan0000000/article/details/73896491
求解斐波那契数列是递归方法的简单应用,那么如何使用递归方法解决比较繁琐的问题呢?
我们这里就举一个比较经典的例子--汉诺塔(Tower of Hanoi)问题,该问题具体规则如下:
- 有A,B,C三根木杆,A杆上由下到上有大,中,小三个圆盘,现在按照以下要求将三个圆盘从A杆移动到C杆。
- 每次移动一个圆盘;
- 尺寸大的圆盘不能放在尺寸小的圆盘上。
解题思路
1.首先我们只考虑大盘,将中,小盘作为整体,那么归位的过程如下(A杆为源杆,C杆为目标杆):
2.那么中,小盘怎样才可以实现从A杆到B杆呢?此时我们就要只考虑中盘了,A杆为源杆,B杆为目标杆,过程如下:
注意思路2里面的目标杆与思路1里面的目标杆不同,但是有没有发现,思路2和思路1中的移动顺序及其的相似呢?
3.上一个思路中已经将中,小两个盘从A杆移动到B杆,最后,我们参照思路2将中,小两个盘从B杆移动到C杆就大功告成了,此时的B杆为源杆,C杆为目标杆。
我们将以上三个思路总结一下,就可以得出:
//n个圆盘,圆盘从小到大为 1→n
//a为源杆,b为过渡杆,c为目标杆
void Hanoi(int n, char a,char b,char c)
{
//思路2:将n-1个圆盘从A杆到B杆
Hanoi(n - 1, a, c, b);
//思路1:将最大的圆盘从A杆到C杆
Move(n, a, c);
//思路3:将n-1个圆盘从B杆到C杆
Hanoi(n - 1, b, a, c);
}
将以上伪代码可以整理为:
int count;
void Move(int n, char a, char b)
{
count++;
printf("第%d次移动 Move %d: Move from %c to %c !\n",count,n,a,b);
}
void Hanoi(int n, char a, char b, char c)
{
if (n == 1)
{
Move(n, a, c);
}
else
{
Hanoi(n - 1, a, c, b);
Move(n, a, c);
Hanoi(n - 1, b, a, c);
}
}
int main()
{
int n;
printf("请输入汉诺塔的层数:");
scanf(" %d",&n);
Hanoi(n, 'A', 'B', 'C');
return 0;
}