双重河内塔I
双重河内塔问题
又称:双重汉诺塔问题
这是《具体数学:计算机科学基础(第2版)》中的一道课后习题
这道题也是挺有意义的,但是百度上一篇C/C++代码都没有
花了一个晚上推出来思路,然后写出了b问题的代码
我打算写三篇随笔来讲这个问题,这是第一篇
双重河内塔包含 2n 个圆盘,它们有 n 种不同的尺寸,每一种尺寸的圆盘有两个。如通常那样,要求每次只能移动一个圆盘,且不能把较大的圆盘放在较小的圆盘上面。
a 如果相同尺寸的圆盘是相互不可区分的,要把一个双重塔从一根桩柱移动到另一根桩柱需要移动多少次?
b 如果在最后的排列中要把所有同样尺寸的圆盘恢复成原来的从上到下的次序,需要移动多少次?
提示:这是一个难题,实在应该是个“附加题”。
本文章针对a问题,后面两篇随笔针对b问题
这篇难度很低,大佬们可以跳过
经典汉诺塔问题如果理解了,a问题应该不难
经典汉诺塔有n个圆盘,我们设将所有圆盘从A塔-->C塔需要的步数为\(F_n\)
则\(F_1=1\)
又\(F_n = F_{n-1} +1+ F_{n-1}\)
易证\(F_n =2^n -1\)
我们设双重汉诺塔问题中2n个圆盘,完成所有移动的最终步数为\(A_n\)
易证\(A_n=2 \times F_n\)
得\(A_n=2^{n+1}-2\)
代码实现
#include<stdio.h>
int step;
void Move(int id,char from,char to){
printf("第%d步:将%d号型盘子%c-->%c\n",++step,id,from,to);
return ;
}
void Hanio(int n,char spos,char tpos,char epos){
if(n==1){
Move(n,spos,epos);
Move(n,spos,epos);
}
else {
Hanio(n-1,spos,epos,tpos);
Move(n,spos,epos);
Move(n,spos,epos);
Hanio(n-1,tpos,spos,epos);
}
}
int main(){
int n;
scanf("%d",&n);
Hanio(n,'A','B','C');
printf("最后总的步数为%d步\n",step);
}
我是一颗水灵灵的大白菜,
农民伯伯辛勤的耕种着我,
把我带到了菜市场
拿着喷头对着我浇水,
还一边说“好菜啊好菜”