背景(摘自百度):汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
简化:三根柱子分别为起始柱A、辅助柱B及目标柱C。将A中的圆盘借助B一直保持从大到小放置的方式,最后全转移放在C上。
问:如何移动 来实现目的呢?
先来看看实现的操作:
1.我们想将n个圆盘放在c上 是不是需要将最大的圆盘(第N个圆盘)放在C的第一个,而通过之前的规则,我们知道这时候C上必不能有圆盘(否则无法放置),而A上同样因为要取出第N个圆盘,所以不能有其他圆盘在其上。那么在哪里呢?
2.显然,我们可以借助B,将A的N-1个圆盘先放在B上。这样就可以实现第一步操作。但是如何将N-1个圆盘放在B上显然成了另一个难题。
3.所以,完成2需要把A的N-1个圆盘放在B上。多看几遍,有什么发现吗?是的!这和我们的目的近乎相同,不过B为目的柱,C变成了辅助柱子。
4.通过3的分析,我们可以重复1和2的操作:
5.需要将N-2个圆盘放在C上,把第N-1个放在B上。啊这!又重复了,不过是B和C的辅助和目的又换了一次。再重复1和2的操作:
6.需要将N-3个圆盘放在B上,把第N-2个放在C上。。。。。。
就这样一直循环下去,我们就解决了问题1。
7.接下来 我们只需要将B上的N-1个圆盘给C,上述1和2的操作一样,不过将起始柱变成了B,辅助柱变成了A:
8..需要将N-2个圆盘放A上,把第N-1个放在C上。。。。。。
这样就解决了该问题。
这个思想也就是DC(divide and conver),分治求解,先将问题分成几个小块,再针对小块求解。
那么该如何实现呢?显然,我们从上面的规律下就不难发现可以用递归解决该问题!
并且 我们发现了基线条件(跳出递归的条件)是将第一个圆盘放到C上。
所以
#include<stdio.h>
void move(char get,char put)//来将移动操作表示出来
{
printf("%c-->%c\n", get, put);
}
void hanoi(int n, char a, char b, char c)
{
if (n == 1)
move(a, c);//基线条件 跳出循环
else
{
hanoi(n - 1, a, c, b);//A作为起始柱不变,b和c一直交换作用(前6步)
move(a, c);
hanoi(n - 1, b, a, c);//b作为起始柱不变,a和c一直交换作用(后2步)
}
}
int main(void)
{
int m;
printf("起始圆盘数为");
scanf("%d", &m);
hanoi(m, 'a', 'b', 'c');
}