编程小笔记

梵塔问题:
根据古印度神话,在贝拿勒斯的圣庙里安放着一个铜板,板上插有三根一尺长的宝石针。印度教的主神梵天在创造世界的时候,在其中的一根针上摆了由小到大共64片中间有孔的金片。无论白天和黑夜,都有一位僧侣负责移动这些金片,规则是一次只能将一片金片移到另一根针上,而且在任何时候以及一根针上,小片永远在大片的上面。当所有的64片金片都由那根针移到另一根针上时,这个世界就在霹雳中消失。
记得初中的时候玩过这个游戏,但是没仔细去研究。看来出来混迟早是要还的。作为第一个递归入门问题,还是写下来好好纪念一下。

1)把问题抽象出来。用字符A、B、C来表示三根针,这梵塔问题可以表示成下列如图:

(图片来源于网络)

把A中所有的金片移到C柱上(移动到B、C柱上均可,假设我们移到C柱上)。

按照简单到复杂的思路,先考虑A上只有一个金片,我们只需把A上的金片直接移到C处即可。当A柱上的金片N>1时,我们需要借助辅助柱B来实现。进一步思考,当我们只移动最小的金片至次大的金片(即第一个到第N-1个金片),完全不会受到第N个金片的影响。所以自然想到可以用某种循环的步骤——递归,来实现它。

所以我们把从A移动N个金片到C这一过程分成如下步骤:

(1)把A上的N-1个金片移动到B。

(2)把A上的最后一个金片移动到C。

(3)把B上N-1个金片移动到C。

步骤(1)、(3)类似,但是不是完全相同。我们可以把(1)进一步细分:

1.把A上N-2个金片移动到C柱。(和我们最外层的过程一致。)

2.把第N-1个金片移动到B。

3.把C柱上N-2个金片移动到B。

我一直认为递归的关键是找出核心的循环步骤,就像找周期函数的周期一样。还有一点就是解决第N个问题和第N-1个问题之间不受影响。(第二点有待考证,只是一种感觉)。

下面是代码:

//test hanoi
#include<iostream>
using namespace std;
const int N = 3;	//设置初始A柱上的金片数目
void move(char from,char to) //定义一个move函数来表示把一个金片从一个柱移动到另一个柱
{
cout<<"From"<<from<<"to"<<to<<endl;
}
void hanoi(int n,char p1,char p2, char p3) //定义函数hanoi表示把p1上的N个金片移动到p3上
{
if(n==1)
{
	move(p1,p3);
}else{
hanoi(n-1,p1,p3,p2);
move(p1,p3);
hanoi(n-1,p2,p1,p3);
	}
}
int main()
{
hanoi(N,'A','B','C');
return 0;
}

下面来考虑一下把N个金片从A柱移动到C柱一共移动了多少步:

设把A柱上的N-1个金片移动到B柱用了An-1步,把第N个金片从A柱移动到C柱用了1步。再把B柱上N-1个金片移动到C柱也用了An-1步,所以一共用了An =  2*An-1 +1. ( A1  =1).下面就是一个数列问题。An+1 =2*(An-1  +1);等比数列搞定它。得到An=2^n -1.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值