汉诺塔的移动次数和移动过程

问题描述

有三根柱子 A B C ,A柱上有 n n n 个圆盘,最大的一个在底下,其余一个比一个小,依次叠上去。将所有在 A 上的圆盘移动到 C ,小盘只能在大盘上面。

计算移动次数

n = 1 n =1 n=1 时,A->C 移动一次
n = 2 n=2 n=2 时 ,A->B , A->C , B->C, 移动三次
n = 3 n=3 n=3 时 ,A ->C , A->B , C->B , A->C , B->A , B->C , A->C , 移动七次
设移动 n n n 个盘需要移动 g(n) 次,分三个步骤完成:

  1. n n n 个盘上的 n − 1 n-1 n1 个盘子借助 C 柱 从 A 柱移动到 B柱,需要 g(n-1) 次
  2. 将第 n n n 个盘从 A 柱移动到 C 柱 ,需要移动 1 次
  3. 将 B 柱上的 n − 1 n-1 n1 个盘借助 A 柱 移动到 C 柱,需要 g(n-1)次
    综上所述,递归关系为:
    g ( n ) = 2 g ( n − 1 ) + 1 g(n) = 2g(n-1) + 1 g(n)=2g(n1)+1
    初始条件为: g ( 1 ) = 1 g(1) = 1 g(1)=1
程序源代码
#include<stdio.h>
double g(int n){
	double s;
	if(n == 1)
		s = 1;
	else
		s = 2*g(n-1)+1;
	return s; 
} 

int main(){
	int n;
	printf("请输入盘片数n:");
	scanf("%d",&n);
	if(n<=40)
		printf("%d盘的移动次数为:%0.0f\n",n,g(n));
	else
		printf("%d盘的移动次数为:%.4e\n",n,g(n));
	return 0;
	
}

移动过程

设递归函数 hn(int n,char a,char b,char c) 表示把 n 个盘从 A 柱 借助 B 柱 移动到 C 柱的过程, 函数 mv(char x,char y) 表示 X -> Y
n = 1 时,mv(a,c)
n > 1 时, 分三步:

  1. n n n 个盘上的 n − 1 n-1 n1 个盘子借助 C 柱 从 A 柱移动到 B柱,即 hn(n-1,a,c,b)
  2. 将第 n n n 个盘从 A 柱移动到 C 柱 ,mv(a,c)
  3. 将 B 柱上的 n − 1 n-1 n1 个盘借助 A 柱 移动到 C 柱,hn(n-1,b,a,c)
程序源代码
#include<stdio.h>
int k = 0;
void mv(char x,char y){
	printf("%c --> %c\t",x,y);
	k++;
	if(k % 5 == 0)
		printf("\n");
}

void hn(int n,char a,char b,char c){
	if(n == 1)
		mv(a,c);
	else{
		hn(n-1,a,c,b);
		mv(a,c);
		hn(n-1,b,a,c);
	}
}
int main(){
	int n;
	printf("请输入盘片数n:");
	scanf("%d",&n);	
	hn(n,'A','B','C');
	printf("\n总共移动的次数->%d",k);
	return 0;
	
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值