1.概述
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
2.图解
如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数
(1)n==1
第1次 1号盘 A---->C sum = 1 次
(2) n == 2
第1次 1号盘 A---->B
第2次 2号盘 A---->C
第3次 1号盘 B---->C sum = 3 次
(3)n == 3
第1次 1号盘 A—->C
第2次 2号盘 A—->B
第3次 1号盘 C—->B
第4次 3号盘 A—->C
第5次 1号盘 B—->A
第6次 2号盘 B—->C
第7次 1号盘 A—->C sum = 7 次
故移动次数为:。
下面求解过程:
将f(n, a, b, c)转化分解为如下三个子问题:
①f(n - 1, a, c, b),即将a棒上面的n-1个盘移到b棒,借助c棒。
②move(a, c),即将在a棒上的一个盘移到c棒。
③f(n - 1, b, a, c),即将b棒上面的n-1个盘移到c棒,借助a棒。
以此解决上述3个问题,即完成对原问题的求解。但问题①和③如何解决呢?可以发现子问题①和③与原问题是相同问题,只不过n变成了n-1。按照递归的思想,可以用相同的方法,所以分别对①和③子问题转化转化分解后的最终子问题只有一个盘为止。
代码:
#include <bits/stdc++.h>
using namespace std;
void move(char getone, char putone)
{
cout<<getone<<"-->"<<putone<<endl;
}
void hanoit(int n,char a,char b,char c)
{
if(n == 1)
{
move(a,c);
}
else
{
hanoit(n-1,a,c,b);
move(a,c);
hanoit(n-1,b,a,c);
}
}
int main()
{
int n;
cin>>n;
hanoit(n,'a','b','c');
//system("pause");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N,M;
cin>>N>>M;
int n,r,s;
char c[3]={'A','B','C'};
n=1;
while((M&1)==0)
{
n++;
M=M>>1;
}
M=M>>1;
r=(N+n)%2;
if(r)
{
s=M%3;
printf("#%d: %c->%c\n",n,c[s],c[(s+1)%3]);
}
else
{
s=2-(M+2)%3;
printf("#%d: %c->%c\n",n,c[s],c[(s+2)%3]);
}
printf("%d\n",(1<<N)-1);//最小移权动步数
return 0;
}