汉诺塔问题

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 次
 

故移动次数为:2^{n}-1

下面求解过程:

 

将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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值