介绍
首先,来介绍一下汉诺塔问题:
这个问题是说,此地有3根柱子,分别为A,B,C,在A的柱子上,放着n个自下而上,由大到小依次放置的盘子,我们要在保持原本的顺序的情况下,将盘子全部从A移动到C。
操作过程中,一次只能移动一个,且保持下面的盘子比上面的盘子大,在遵守前面的条件下,盘子可以在3个柱子中随意移动。
在了解完问题后,我们就来使用递归的思想来计算问题中需要用到的步数和过程。
思路:
我们先来列举几个情况来看一下是个什么情况,顺便捋一下思路
1.当圆盘只有一个,即n=1时:
当圆盘只有一个时,我们只用将A直接移到C即可,只需要一步。
当n=2时,我们就需要分步数了:
第一步:先将红色的移到B柱子;
第二步:将黑色的移到C柱子;
第三步:将红色的移到C柱子。
当n3时
先上图看一下
仔细观察,可以发现:当我们把红色和蓝色看成一个主体时,它所需要的步骤就与n=2时相同了,只需要三步
绿色框出来的步骤
此时先将红蓝看做一个整体
第一步:将红蓝一同从A杆移到B杆;
第二步:将底盘的黑色盘从A杆移动到C杆;
第三步:将红蓝再一同从B杆移动到C杆。
再将红蓝当成一个n=2的情况去分析:(将上面的三步再细分)
第一步:与n=2的情况相同,只是目标杆从C杆变成了B杆,起始位置不变;
第二步:将底盘从A杆移动到C杆,只用一步;
第三步:任然与n=2的情况相同,只是起始位置从A杆变成了B杆,目标杆不变。
具体过程总结一下就是:
当n=1时,直接将盘从A盘移动到C盘即可,只需一步;
当n>1时,首先需要将(n-1)的盘子移动到中间杆B杆,然后再将底盘移动到C杆,最后将(n-1)的盘子移动到C杆,只要(n-1)>1,就会一直重复上面的三步。
公式总结
次数:(设次数为count)
n==1时,count(n)=1;
n>1时,count(n)=count(n-1)+1+count(n-1)
=2*count(n-1)+1
移动代码实现:
#include <stdio.h>
int count(int m)
{
if (m == 1)
{
return 1;
}
else
{
return 2*count(m - 1) + 1;
}
return 0;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count(num);
printf("共走了%d步\n", ret);
return 0;
}
过程:(设函数为Hanoi)
n==1时,就只有一步 A->C;
n>1时,首先将(n-1)从A杆(起始杆)通过C杆(中转杆)移动到B杆(目标杆) A->B
然后将底盘直接从A杆移动到C杆 A->C
最后再将(n-1)从B杆(起始杆)通过A杆(中转杆)移动到C杆(目标杆) B->C
过程代码实现:
#include <stdio.h>
void Hanoi(int n, char sp, char mid, char end)
{
if (n == 1)
{
printf("%c->%c ", sp, end);
}
else
{
Hanoi(n - 1, sp, end, mid);
printf("%c->%c ", sp, end);
Hanoi(n - 1, mid, sp, end);
}
}
int main()
{
int num = 0;
scanf("%d", &num);
Hanoi(num, 'A', 'B', 'C');
return 0;
}
可能有些部分解释的不够清楚,还请多多包涵,如有错误,欢迎指正。
这个汉诺塔的问题真的就,抽象。然后自己也笨,总想着去用脑子想完全程,然后脑子就报废了,啊哈哈。