在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘,求把圆盘从下面开始按大小顺序重新摆放在另一根柱子上需要移动多少次。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
解答:
我们可以拿n=3的时候举例子:
易知f(1)=1,f(2)=3,f(3)=7……;
当n=2时候(1,2,3分别表示小中大三块盘子):
当n=3时候:
n=3的前三步就是重复n=2时候,把小的两块移动到另一个一个柱子。
然后就是将3移动到另一块柱子上,在继续重复n=2把小的两块移动到另一个(指存在3的一个)柱子上。
扩展到n,即f(n)=2*f(n-1)+1
这就变成了递归问题!!
只计算次数,简单的c++程序如下:
#include <iostream>
using namespace std;
int main()
{
int num,cont=0,a=1;
cout<<"请输入需要移动的盘子数目:"<<endl;
cin>>num;
int val(int); //函数声明
if(num==0){
cout<<"输入的数字必须大于0!"<<endl;
return -1;
}
else
cout<<"需要"<<val(num)<<"次"<<endl;
return 0;
}
int val(int n){
int c;
if(n==1) c=1;
else c=2*val(n-1)+1;
}
显示步骤:
每个步骤都是 将n-1个盘子从A移到B,把最下面个移到C,然后把N-2个从B移到A,第N-1个移到C,如此继续下去。
#include<iostream>
using namespace std;
int main()
{
void hanoi(int n,char one,char two,char three);
int m;
cout<<"输入盘子数:";
cin>>m;;
hanoi(m,'A','B','C');
}
void hanoi(int n,char one,char two,char three)
{
void move(char x,char y);
if (n == 1)
{
move(one,three);
}
else
{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}
void move(char x, char y)
{
cout<<x<<"-->"<<y<<endl;
}
详解二、
汉诺塔:
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆环,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
- 每次只能移动一个圆盘;
- 大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
为了解决这个问题,不妨假设已经知道怎样移动N-1个圆环了。现在,为了把起点盘上的圆环移动到目标盘,需要做如下操作:
1、把N-1个圆环从起点盘移动到(当前)没有任何圆环的过度盘;
2、把最后一个圆环从起点盘移动到目标盘;
3、把N-1个圆环从国度盘移动到目标盘(模仿1和2的操作方法来实现)。
参考图:
三个圆盘的汉诺塔
四个圆盘的汉塔:
void hannoi (int n, char A, char B, char C) // 把A盘里面的圆圈转移到C盘里面【A--C】。
{
if (n == 1)
{
cout << "移动圆圈" << n << "从盘" << A << "盘" << C << endl; //把最后一个圆环从起点盘移动到目标盘。
}
else
{
hannoi (n-1, A, C, B); // 把N-1个圆环从起点盘移动到(当前)没有任何圆环的过度盘;通过B、C盘在此函数调用中调用位置的互换,来实现把N-1个圆环从A盘到B盘的转移【A--B】。
cout << "移动圆圈" << n << "从盘" << A << "盘" << C << endl;
hannoi (n-1, B, A, C); // 把N-1个圆环从国度盘移动到目标盘(模仿1和2的操作方法来实现);通过A、B盘在此函数调用中位置的互换,来实现N-1个圆环从B盘到C盘的转移【B--C】。
}
}