游戏规则:
有A,B,C三根针,将A针上N个从小到大叠放的盘子移动到C针,一次只能移动一个,不重复移动,小盘子必须在大盘子上面。
问题:
总的移动次数是多少?
分析:
(1)n == 1
第1次 1号盘 A—->C sum = 1 次
(2) n == 2
第1次 1号盘 A—->B
第2次 2号盘 A—->C
第3次 1号盘 B—->C sum = 3 次
(3)n == 3
第1次 1号盘 A—->C
第2次 2号盘 A—->B
第3次 1号盘 C—->B
第4次 3号盘 A—->C
第5次 1号盘 B—->A
第6次 2号盘 B—->C
第7次 1号盘 A—->C sum = 7 次
不难发现规律:1个圆盘的次数 2的1次方减1
2个圆盘的次数 2的2次方减1
3个圆盘的次数 2的3次方减1
。 。 。 。 。
n个圆盘的次数 2的n次方减1
故:移动次数为:2^n – 1
而对于汉罗塔的具体移动方法,我从很久之前就开始疑惑,对于盘子数量为 1 ,为 2,为 3 这个我们都好说,也好模拟计算,至于移动的次数也很容易计算出来,从而推导出来 n 个盘子的移动次数,但是你有没有和我之前一样的困惑呢?具体如何移动的呢?其实真的不用去细细的琢磨,我们知道无非就是三个盘子之间的移动呗,但是如果从从整体的盘子移动的去向来考虑,我们要的结果就是将 A 针上的所有盘子转移到 C 盘子上,而且在移动的过程中有一个限制条件就是小盘子一定在大盘的上面,我们由简到繁来分析:
如果 A 针上有一个盘子,我们就直接将该盘子移动到 C 盘子上,就 OK 了!
如果 A 针上有 n 个盘子,那么我们就要借助 C 针将 n-1 个盘子移动到 B 针上(这时 B 针是过度针),再将第 n 个盘子移动到 C 针上,这样完了之后,B 针上有 n-1个盘子,C 针上有 1 个盘子,而 A 针上没有盘子,但是 B 针上的 n-1 个盘子都比 C 针上的那一个盘子小,于是这时,我们需要将B 针上的转移到 C 针,这时 A 针就是过度针了~
代码实现:
#include <iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
void Move(int n,char a,char b,char c)
{
if(n==1)///如果一个盘子就直接转移
printf("Move sheet %d form %c to %c\n",n,a,c);
else///如果是 n 个盘子
{
Move(n-1,a,c,b);///我们首先要将 1~n-1 个盘子以 C 针作过度转移到 B 针上
printf("Move sheet %d form %c to %c\n",n,a,b);
Move(n-1,b,a,c);///我们再将 B 针上的 1~n-1 个盘子以 A 针作过度转移到 C 针上
}
}
int main()
{
int n;
printf("请输入盘数:\n");
scanf("%d",&n);
Move(n,'A','B','C');///将 n 个盘子以 B 针作过度转移到 C 针上
return 0;
}