C语言实现 蓝桥杯 算法提高 汉诺塔

试题 算法提高 汉诺塔

                                                                                  蓝桥杯试题解答汇总链接

资源限制

       时间限制:1.0s 内存限制:256.0MB


问题描述

       汉诺塔是一个古老的数学问题:
  有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
  每次只能移动一个圆盘;
  大盘不能叠在小盘上面。
  提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。

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


输入格式

       一行,包含2个正整数,一个是N,表示要移动的盘子数;一个是M,表示最少移动步数的第M步


输出格式

       共2行。
  第一行输出格式为:#No: a->b,表示第M步骤具体移动方法,其中No表示第M步移动的盘子的编号(N个盘子从上到下依次编号为1到n),表示第M步是将No号盘子从a杆移动到b杆(a和b的取值均为{A、B、C})。
  第2行输出一个整数,表示最少移动步数。


样例输入
2

样例输出
#2: A->B
7

数据规模与约定
0<N<20,0<M<=最少移动步数

试题解析

下面举例的3种情况如不好理解建议跟着思路自己画图理解!
假设n=1:那么直接需要一步把第1个(即第n个)从A移到C即:#1: A->C共1步
假设n=2:那么需要把第1个(即第n-1个)从A移动到B;在把第2个(即第n个)移动到C;然后把第1个(即第n-1个)从B移动到C即#2: A->B,#1: A->C,#2: B->C共3步
假设n=3:那么需要先把第1个(即第n-2个)从A移动到C然后把第2个(即第n-1个)从A移动到B然后把第1个(即第n-2个)从C移动到B然后把第3个(即第n个)从A移到C然后把第1个(即第n-2个)从B移到A然后把第2个(即第n-1个)从B移到C然后把第1个(即第n-1个)从A移到C即:#1: A->C,#2: A->B,#1: C->B,#3: A->C,#1: B->A,#2: B->C,#1: A->C共7步
总结规律:先假设f(n)为把n个盘子从一根柱子全部移动到另外一根柱子所需要的最少步数。要想实现f(n)需要分三步如下图在这里插入图片描述
要实现f(n-1)有可以按照f(n)的思路分为三个步骤,这就是递归的思路,根据这个可以总结出一个等式f(n+1)=2f(n)+1(n为任意的正整数)即
f(n+1)+1=2(f(n)+1)又f(n)>0所以数列f(n)+1为以2为首项2为公比的等比数列
可以求出f(n)=2n-1
但题目不仅要求最少的步数还要求给出第m步的操作过程,所以我们需要根据上面的分三步思路定义新的函数Hanoi(n,A,B,C),它表示的意思是把在A的n块通过B的辅助移动到C(不通过C在n-1大于2时是无法直接移动到B的)那么根据上面的三步走可以如此递归
要实现Hanoi(n,A,B,C)
先得实现Hanoi(n-1,A,C,B)即把在A的n-1块通过C的辅助移动到B
然后A上只剩下第n块所以把第n个从A移动到C即:#n: A->C
然后实现Hanoi(n-1,B,A,C)即把在B的n-1块通过A的辅助移动到C
在添加一个计步器count在第m步时输出即可


代码
#include<stdio.h>
// n,m对应题意,count是计步器 
int n,m,count=0;
/**
 * 在只有一块的情况下直接把这一块从A移到C不需要借助B
 * 1.要把n个盘子借助B移到C就先要把n-1个在A的盘子借助C移到B
 * 2.现在n-1个盘子在B,就把第n个从A移到C
 * 3.然后把n-1个在B上的盘子借助A移动到C 
 */
void Hanoi(int n,char A,char B,char C){
	if(n==1){
		count++;
		if(count==m){
			printf("#%d: %c->%c\n",n,A,C);
		}
		return;
	}
	Hanoi(n-1,A,C,B);
	count++;
	if(count==m){
		printf("#%d: %c->%c\n",n,A,C);
	}
	Hanoi(n-1,B,A,C);
}
int main(){
	scanf("%d%d",&n,&m);
	/**
	 * 先要把n个在A上的盘子借助B放到C 
	 */
	Hanoi(n,'A','B','C');
	printf("%d",count);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Derrick-Xu

谢大哥打赏,我会继续努力!

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

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

打赏作者

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

抵扣说明:

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

余额充值