相信很多人都玩过汉诺塔游戏,今天来讨论下这个游戏的最优解的程序实现。
假设有A、B、C三根柱子,A是起始柱,B是目标柱,C是中转柱。
我们先来分析只有一层汉诺塔的情况,这个比较简单,只需要将A上面的块放到B上面就行了。
接下来分析两层汉诺塔的情况,总共分三步,首先将上面的一块放到C,然后将下面那块大的放到B,接着将C柱上面的那块放到B上面。
依次逻辑类推,我们假设N层的汉诺塔,那么大致也是分为三个步骤,
1.就是将上面的N-1块放到中转柱C。这个怎么移呢,就是将B作为中转站,将C作为目标站,层数是N-1层。
2.然后将A的最后一块放到目标柱B上面
3.接着将C上面的N-1块移到目标柱B上面。这时是将C当作起始柱,A当作中转柱,B还是目标柱,层数是N-1层,这样就能将C的N-1块移到B上去。
这个利用到递归的思想,先申明函数
hannuo(int n, char x, char y, char z) //n是层数 x是起始柱 y是目标柱 z是中转柱
那么这三个步骤可以用用函数表示为
hannuo(n, x, y, z)
{
hannuo(n-1, x, z, y); //参见红字 步骤一
Printf(“%c -> %c”, x, y); //将A的最后一块放到 B 步骤二
Hannuo(n-1,z, y, x); //参见红字 步骤三
}
这个函数还不够完善,需要递归的初始条件完整代码如下
hannuo(n, x, y, z)
{
if(n== 0)
{
//啥都不做
}
else
{
hannuo(n-1, x, z, y); //参见红字 步骤一
Printf(“%c -> %c”, x, y); //将A的最后一块放到 B 步骤二
Hannuo(n-1,z, y, x); //参见红字 步骤三
}
}
int main(void)
{
Hannuo(5,’A’, ‘B’, ‘C’);
Return0;
}
分析这个代码,这个代码的精髓,或者说难点,就在于中间的printf,它的表征意义就是将起始到目的的这一过程给打印出来,思想是利用递归,分成最原始的一小份一小份来打印。
同时我们也可以分析步骤的数量
一层是1
二层是3
以上是我们手动分析的,
然后是我们的N层,他等于N-1层的步骤数+ 一个步骤+ N-1层的步骤数
Num(n) = 2 * num(n-1) + 1
Num(1) = 1
这个可以利用高中知识来解决,亦或者通过前几项发现规律,找到公式,然后在利用归纳法验证公式的正确性即可。