[模板题]汉诺塔(hanoi)问题

8 篇文章 1 订阅
6 篇文章 0 订阅

题目来源 网络

算法标签 递归,模拟

故事背景

汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。 [2]

不管这个传说的可信度有多大,如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。这需要多少次移动呢?这里需要递归的方法。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2^n-1。n=64时,假如每秒钟一次,共需多长时间呢?一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下:18446744073709551615秒
这表明移完这些金片需要5845.54亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。真的过了5845.54亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。

题目描述

有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆环,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:

1.每次只能移动一个圆盘;
2.大盘不能叠在小盘上面。

提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。

问:如何移?最少要移动多少次?

图示

我们直接模拟过程

n==1时:

在这里插入图片描述
在这里插入图片描述

n==2时:

在这里插入图片描述
将n-1块移动到B辅助柱
在这里插入图片描述
将第n块移动至目标柱
在这里插入图片描述
将辅助柱上的物体全部移动至目标值
在这里插入图片描述
完成

n==3

在这里插入图片描述
将n-1块移动至B辅助柱

在这里插入图片描述
将起始柱上的物体全部移动到目标柱上
在这里插入图片描述
将辅助柱上的所有物体移动到目标柱上
在这里插入图片描述
完成

思路

从所画图内的逻辑上来说,
当n==1时,直接从a放置到c				  //if(n==1)cout<< a->c;
当n>=2时,1.将n-1块从起始柱a移动到辅助柱b, //f(n-1,a,c,b)  <- f(int n,int a,int b,int c) <- //n块数,a起始柱,b辅助柱,c终点柱
		 2.将第n块从起始柱a移动到目标柱c, //f(n-1,a,b,c)
		 3.将n-1块从辅助柱b移动到目标柱c, //f(n-1,b,a,c)
		 4.完成

本题最重要还是任务的分解与递归计算,重在推论的逻辑。

伪码

1.if n=1 	then move(a,c)
2.else 		hanoi(n-1,a,b)
3.			move(a,c)
4.			hanoi(n-1,b,c)

时间复杂度

o(n)	=	2^n

因为:
if n=1  then T(n)=1
else  		 T(n)=2T(n-1)+1

T(n)	=	2T(n-1)+1
		=   2[2*T(n-2)+1]+1;
		=   2^(2T)*(n-2)+2+1;
			...
		=	2^(n-1)*T(1)+2^(n-2)+2^(n-3)+...+3+2+1;
		=	2^(n-1)*1+2(n-1)-1
		=	2^n-1
		
T(n) 	=	2^n-1

题目代码

#include<iostream>

using namespace std;

void hanoi(int n,char a,char b,char c)
{
    if(!(n-1)){cout<<a<<"->"<<c<<endl;return ;}//把剩下得一块从a->c
    
    hanoi(n-1,a,c,b);//把n-1从a->b
    cout<<a<<"->"<<c<<endl;
    hanoi(n-1,b,a,c);//把n-1从b->c
}
int main()
{
    int n;
    cin>>n;
    
    hanoi(n,'a','b','c');
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俺叫西西弗斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值