汉诺塔问题及其变型
2016-02-25 22:22
323 查看
一.汉诺塔问题
(1)问题描述:
有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。
将A柱子上的圆盘全部移动到C柱子上。每次只能移动一个圆盘,而且在移动的过程中,
三个柱子上的圆盘始终保持大圆盘在下,小圆盘在上。
(2)程序输入:
A柱子上的圆盘数,当输入0时,程序结束。
(3)程序输出:
圆盘移动的过程和圆盘移动的总次数。
(4)递推公式:
H(1) = 1.
H(n) = 2 * H(n-1) + 1 = 2 ^ n - 1.
二.汉诺塔问题的变型
(1)问题描述:
有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。
将A柱子上的圆盘移到C柱子上。每次只能移动一个圆盘,而且在移动的过程中,
三个柱子上的圆盘始终保持大圆盘在下,小圆盘在上。
另外,不允许直接从A柱子移动到C柱子或直接从C柱子移动到A柱子,
即每次移动一定是移动到中间柱子B或者从中间柱子B移走。
例如,当A柱子上只有一个圆盘时,
首先将这个圆盘从A柱子移动到中间柱子B,再从中间柱子B移动到C柱子,总共移动次数是2。
(2)程序输入:
A柱子上的圆盘数,当输入0时,程序结束。
(3)程序输出:
圆盘移动的过程和圆盘移动的总次数。
(4)递推公式:
H(1)= 2.
H(n) = 3 * H(n-1) + 2.
(1)问题描述:
有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。
将A柱子上的圆盘全部移动到C柱子上。每次只能移动一个圆盘,而且在移动的过程中,
三个柱子上的圆盘始终保持大圆盘在下,小圆盘在上。
(2)程序输入:
A柱子上的圆盘数,当输入0时,程序结束。
(3)程序输出:
圆盘移动的过程和圆盘移动的总次数。
(4)递推公式:
H(1) = 1.
H(n) = 2 * H(n-1) + 1 = 2 ^ n - 1.
//源代码已经在VS2012编译通过。 #include<windows.h> #include<string> #include<iostream> using namespace std; //将num号圆盘从x柱子移动到y柱子 void Move(int num,string x,string y) { cout << num << "号圆盘:" << x << "移动到" << y << endl; } //将A柱子上的n个圆盘移动到C柱子上,B柱子作为中间柱子,返回移动总次数 long long Hannoi(int n,/*源柱子*/string A,/*中间柱子*/string B,/*目标柱子*/string C) { long long cnt1,cnt2; if (n == 1) { //A柱子上只有一个圆盘时,直接将这个圆盘移动到C柱子上,移动次数是1 Move(1,A,C); return 1; } else { /****************************************************************** 1 1 2 1 1 2 3 => 2 => 2 => 3 4 3 3 4 5 5 4 4 5 5 *** *** *** *** *** *** *** *** *** *** *** *** A B C A B C A B C A B C *******************************************************************/ //将A柱子上的最上面n-1个圆盘移动到中间柱子B上 cnt1 = Hannoi(n - 1,A,C,B); //将A柱子上的最下面一个圆盘移动到C柱子上 Move(n,A,C); //将中间柱子B上的n-1个圆盘移动到C柱子上 cnt2 = Hannoi(n - 1,B,A,C); return cnt1 + cnt2 + 1; } } int main () { cout << "汉诺塔问题的解决方案:" << endl; long long cnt; int n; cout << "请输入A柱子上的圆盘数:"; while(scanf("%d",&n) != EOF) { if(n == 0) { break; } cnt = Hannoi (n,"A","B","C"); cout << n << "个圆盘的移动总次数:" << cnt << endl; cout << "请输入A柱子上的圆盘数:"; } system("pause"); return 0; }
二.汉诺塔问题的变型
(1)问题描述:
有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。
将A柱子上的圆盘移到C柱子上。每次只能移动一个圆盘,而且在移动的过程中,
三个柱子上的圆盘始终保持大圆盘在下,小圆盘在上。
另外,不允许直接从A柱子移动到C柱子或直接从C柱子移动到A柱子,
即每次移动一定是移动到中间柱子B或者从中间柱子B移走。
例如,当A柱子上只有一个圆盘时,
首先将这个圆盘从A柱子移动到中间柱子B,再从中间柱子B移动到C柱子,总共移动次数是2。
(2)程序输入:
A柱子上的圆盘数,当输入0时,程序结束。
(3)程序输出:
圆盘移动的过程和圆盘移动的总次数。
(4)递推公式:
H(1)= 2.
H(n) = 3 * H(n-1) + 2.
//源代码已经在VS2012编译通过 #include<windows.h> #include<string> #include<iostream> using namespace std; //将num号圆盘从x柱子移动到y柱子 void Move(int num,string x,string y) { if(x == "B" || y == "B") { cout << num << "号圆盘:" << x << "移动到" << y << endl; } else { cout << num << "号圆盘:" << x << "移动到" << "B" << endl; cout << num << "号圆盘:" << "B" << "移动到" << y << endl; } } //将A柱子上的n个圆盘移动到C柱子上,B柱子作为中间柱子,返回移动总次数 long long Hannoi(int n,/*源柱子*/string A,/*中间柱子*/string B,/*目标柱子*/string C) { long long cnt1,cnt2,cnt3; if (n == 1) { //A柱子上只有一个圆盘时,首先将这个圆盘移动到中间柱子B上,再从中间柱子B上移动到C柱子上 //移动次数是2 Move(1,A,C); return 2; } else { /*************************************************************************** 1 1 2 1 1 1 1 2 3 => 2 => 2 => 2 => 2 => 3 4 3 3 3 3 4 5 5 4 5 4 4 5 4 5 5 *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** A B C A B C A B C A B C A B C A B C ***************************************************************************/ //将A柱子上的最上面n-1个圆盘移动到C柱子上 cnt1 = Hannoi(n - 1,A,B,C); //将A柱子上的最下面1个圆盘移动到B柱子上 Move(n,A,B); //将C柱子上的n-1个圆盘移动到A柱子上 cnt2 = Hannoi(n - 1,C,B,A); //将B柱子上的1个圆盘移动到C柱子上 Move(n,B,C); //将A柱子上的n-1个圆盘移动到C柱子上 cnt3 = Hannoi(n - 1,A,B,C); return cnt1 + cnt2 + cnt3 + 2;//cnt1 == cnt2 == cnt3 } } int main () { cout << "汉诺塔问题的解决方案:" << endl; long long cnt; int n; cout << "请输入A柱子上的圆盘数:"; while(scanf("%d",&n) != EOF) { if(n == 0) { break; } cnt = Hannoi (n,"A","B","C"); cout << n << "个圆盘的移动总次数:" << cnt << endl; cout << "请输入A柱子上的圆盘数:"; } system("pause"); return 0; }
相关文章推荐
- 有关数据库SQL递归查询在不同数据库中的实现方法
- C#中的递归APS和CPS模式详解
- WinForm实现按名称递归查找控件的方法
- 使用SqlServer CTE递归查询处理树、图和层次结构
- C#中的尾递归与Continuation详解
- C#递归实现显示文件夹及所有文件并计算其大小的方法
- php递归创建目录的方法
- PHP递归创建多级目录
- Javascript递归打印Document层次关系实例分析
- oracle 使用递归的性能提示测试对比
- 使用curl递归下载软件脚本分享
- Perl脚本实现递归遍历目录下的文件
- JavaScript的递归之递归与循环示例介绍
- C# 递归查找树状目录实现方法
- 全排列算法的非递归实现与递归实现的方法(C++)
- php递归列出所有文件和目录的代码
- java递归菜单树转换成pojo对象
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- 一个JavaScript递归实现反转数组字符串的实例
- Java中的递归详解(用递归实现99乘法表来讲解)