【递归】汉诺塔(c++)(信息学奥赛一本通1205:汉诺塔问题 的题解)

注意了,想看 信息学奥赛一本通1205:汉诺塔问题 的人注意了,把思路看完,代码我最后给 其实就是作者不想再写一篇文章

描述

阅读部分

汉诺塔是非常经典的一道递归题目。

程序实现

(1)程序目的

运用递归来解汉诺塔问题

(2) 程序构思

由上述对n个铁盘的汉诺塔问题分析中,我们定义铁盘原先所在的桩为“来源桩”(Source),铁盘欲移往的桩为“目的桩”(Destination),而另一个桩为“辅助桩”(Auxliiary)。

当铁盘数目 大于 00 时:

将前N-1N−1个铁盘从来源桩移往辅助桩

将编号为NN的铁盘从来源桩移往目的桩

将前N-1N−1个铁盘从辅助桩移往目的桩

递归执行部分:

将前N-1N−1个铁盘从来源桩移往辅助桩

将编号为NN的铁盘从来源桩移往目的桩

将前N-1N−1个铁盘从辅助桩移往目的桩

【题目部分】

相传在某一座古庙有33根木桩,有2424个铁盘由小到大地放置在其中一根木桩上,庙中流传者一个传说:“如果有一天能把24个铁盘,从其中一个木桩移至另一根木桩,且必须遵守着以下两个原则:(1)每一天只能搬动一个铁盘,而且只能从最上面的铁盘开始搬动。 (2)必须维持较小的铁盘在上方的原则,则当24个铁盘完全搬至另一个木桩时,世界就会永久和平”这个问题就是著名的汉诺塔(Tower of Hanoi )问题。

如图:三根柱子分别为:a、b、c柱

输入

输入一个数nn,即铁盘的个数。

铁盘从上到下一次编号为:1,2,3, \dots ,n1,2,3,…,n

输出

输出铁盘移动的具体步骤。

输入样例 1 

4

输出样例 1

move 1 from a to b
move 2 from a to c
move 1 from b to c
move 3 from a to b
move 1 from c to a
move 2 from c to b
move 1 from a to b
move 4 from a to c
move 1 from b to c
move 2 from b to a
move 1 from c to a
move 3 from b to c
move 1 from a to b
move 2 from a to c
move 1 from b to c

---------------------------------------------------------------------------------------------------------------------------------

思路:

相信很多人看到这道题就蒙了,这道题看起来好难啊

其实,只要搞清楚我们的递推式,就很容易能做出这道题

首先分析一下,我们如果要把在1号柱子的4号铁盘移到3号柱子,我们需要干什么?我们首先需要把4号铁盘上面的所有铁盘移到2号柱子上,然后把4号铁盘放到3号柱子

这里我们发现,4号铁盘原本在的1号柱子,我们称为“起始柱”,2号柱子辅助我们移动,我们称为“辅助柱”,移到3好柱子是4号铁盘的目标,我们叫他“目标柱”

我们分析一下怎么写代码

首先,我们需要写一个函数吧?那函数就叫f(n,a,b,c)这个函数中,n代表要移动的是第n个铁盘,

a、b、c分别代表起始柱、辅助柱、目标柱,也就是把a柱设为其实柱,把b柱设为辅助柱,把c柱设为目标柱

f(n,a,b,c)就表示把n号铁盘从a柱移到c柱,以b柱为辅助柱

那接下来,我们需要知道递归边界,边界就是n==0的时候,这时我们的移动已经结束了,没有盘子能移了

这样,我们就差不多能写出代码了其实就是作者偷懒不想再写了

具体的思路我们在代码里注释出来

---------------------------------------------------------------------------------------------------------------------------------

代码:

#include<bits/stdc++.h>
using namespace std;
void f(long long n,char a,char b,char c){//其中,a为起始柱,b为辅助柱,c为目标柱 
	//n代表将第n个铁盘从起始柱移到目标柱 
	if(n==0){//如果n==0,说明我们递归到尽头了(没有盘子能移了) 
		return;
	}//否则就是还能继续移动
	f(n-1,a,c,b); //将上面一个盘子从起始柱a出发,以c为辅助柱,以b为目标柱
	//因为将上面一个盘子进行移动,也会移动再上面的盘子,这样,我们就把前n-1个盘子移到了b号柱 
	//我解释一下,我们为什么要移到b号柱?
	//因为我们的目的是移动n号铁盘,我们要将前n-1个盘子都移到b柱,才能将第n个盘子移到c柱 
	cout<<"move "<<n<<" from "<<a<<" to "<<c<<endl;
	//这时,我们已经将第n号铁盘移到了c号柱,那我们就输出答案
	//那我们就应该输出第n号铁盘从a移到c 
	f(n-1,b,a,c);
	//这里很关键,我们需要将上面的n-1个铁盘移到c柱上,这样我们才能保证所有盘子都移到了c柱(具体到主程序解释) 
	//也就是把第n-1个铁盘从b柱出发,以a柱为辅助柱,移到c柱 
}
int main(){
	long long n;
	cin>>n;//要移n个盘子 
	f(n,'a','b','c');//把第n个盘子从a柱出发,以b为辅助柱,移到c柱 
	/*
	这里是解释为什么要把n-1个柱子也移动到c柱 
	假如n==4,我们现将3号盘移到了b柱,那2、1号盘能留在c柱吗?
	当然不能,因为这样4号盘就不能移到c柱了,所以我们要将1、2、3号盘都移到b柱 
	*/
	return 0;
}

其实题目都不难,仔细思考就能做出来

信息学奥赛一本通1205汉诺塔

#include <iostream>//emmm……作者不想写注释了,所以代码的解释,你就看上面那个代码的注释(反正都一样,应该能看懂吧?)
using namespace std;

void hanoi(int n, char from, char to, char usingRod) {
    if (n == 1) {
        cout << from << "->" <<n<<"->"<< to << "\n";
    } else {
        hanoi(n - 1, from, usingRod, to);
        cout << from << "->" <<n<<"->"<< to << "\n";
        hanoi(n - 1, usingRod, to, from);
    }
}

int main() {
    int n;
    cin >> n;
    char a, b, c;
    cin >> a >> b >> c;
    hanoi(n, a, b, c);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值