递归法的应用:求解汉诺塔问题

  • 题目描述:汉诺塔问题是一个经典的问题,其来源据说在19世纪末欧洲的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆自上而下、由小到大顺序串着64个圆盘构成的塔,游戏的目的是将左边A杆上的圆盘借助最右边的C杆,全部移动到中间的B杆上,条件是一次仅能移动一个盘,且不允许大盘放在小盘上面,问最少需要移动多少次。

  • 解法描述:我们可知限制条件为:一次只能移动一个盘,且不允许大盘放在小盘上面。解法为:首先我们设要解决的汉诺塔有n个圆盘,对A杆上的全部n个圆盘从小到大顺序编号,最小的为1号,依次递增,最大的圆盘编号为n。

    • 第一步:假设此时A杆上只有一个圆盘,即汉诺塔只有一层,那么将其移动到B杆上即可。

    • 第二步:对于有n(n>1)个圆盘的汉诺塔,将n个圆盘分为两个部分,上面n-1个圆盘为一个部分,下面编号为n的一个圆盘为另一部分。

    • 第三步:将“上面n-1个圆盘“看成一个整体,为了解决这n个圆盘的汉诺塔可以进行下列操作:

      • 将A杆上的n-1个圆盘借助B杆移到C杆上,此时设C杆上有n个盘子(n = n - 1);
      • 将A杆上剩下的编号为n的盘子移动到B杆上;
      • 将C杆上的n-1个盘子借助A杆移到B杆上;
      • 在将n-1个圆盘从C杆上移动到B杆上和原问题具有具有相同的特征属性,只是问题的规模小于原问题,故我们可以使用递归的方法来求解。
  • 下面就以四个盘子为例,来解释盘子的移动过程:

    • 初始状态的汉罗塔:
      在这里插入图片描述
    • 第一次借助B杆将A杆上的n-1个盘子移动到C杆上并把A杆上的最后一个盘子移动打B杆上后的结果(中途的移动步骤没有体现出来,需要自己下去推导,这里就给出了每次移动后的最终结果):
      在这里插入图片描述
    • 再借助B杆将C杆上的n-1个盘子移动到A杆并将C杆上的最后一个盘子移动到B杆上后的结果:
      在这里插入图片描述
    • 递归对A杆、B杆和C杆上的盘子的移动操作直至最后一个盘子移动到B杆上结束;
      在这里插入图片描述
    • 最后的结果:
      在这里插入图片描述

    编程实现:

#include<iostream>
using namespace std;
void Hanoi(int n, char a, char b, char c, int &count)
{
	if(n == 1)
     	{
      		count++;//移动A杆上的最后一个盘子到B杆
    	}
     	else
	{
   	  	Hanoi(n - 1, a, b ,c, count);            //A 杆借助B杆移动n-1个盘子到C杆
    		count++;                                 //移动A杆上的最后一个盘子到B杆
    		Hanoi(n - 1, c, b ,a, count);           //C杆借助B杆将n-1个盘子移动到A杆
   	}
}
 int main()
{
     	int count,n;
     	cout << "please input the count:";
     	cin >> n;
     	count = 0;
     	Hanoi(n, 'A', 'B', 'C', count);
     	cout << "total = " << count << endl;
     	return 0;
}
  • 测试结果:
    在这里插入图片描述
发布了62 篇原创文章 · 获赞 68 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/magic_world_wow/article/details/83348577