汉诺塔问题,即给三个柱子,起始柱,间接柱,目标柱,在起始柱有n层由下到上由大到小的盘子,目的是将盘子从起始柱放到目标柱,且大小顺序不变,在移动的过程一次只能移动一个,且全程不能出现大盘子在小盘子上面的情况。写一个程序,输入盘子层数n,打印移动过程,求一共移动了几次。
问题分析:
如图所示,一共四个盘子,在移动的过程中总会出现图中的情况,即三个小盘子在间接柱B,将大盘子从起始柱A移动到目标柱C,在想办法将B的小盘子移动到C上。
这就需要先考虑两个过程,即如何将三个小盘子移动到间接柱B,在从间接柱移动到C。首先第一个过程,我们就可以认为如何处理三个盘子从起始柱A通过间接柱C移动到目标柱B(注意,三个柱子是有轮换对称性的,也就是说起始柱,目标柱,间接柱的关系是可以互换的,这也将体现到程序中)。那移动三个盘子,就必然会出现两个盘子出现在间接柱,而让最大的盘子移动到目标柱,在移动两个小盘子即可,这样我们就得到了递归的思路。即处理n个盘子,就考虑处理n-1个盘子,处理n-1个盘子就考虑如何处理n-2个盘子。第二个过程同理,只不过是改为了将盘子从间接柱移动到目标柱。
下面我们来写程序,说明会在注释中进行:
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>int count = 0;void move(char x,char y){printf("%c--->%c", x, y);//打印从哪个柱子到哪个柱子count++;//打印一次就加一次,目的是计算移动了几次}void tower(int n, char ONE, char TWO, char THREE)//注意,除开n,第一个参数的位置永远是起始柱位置,第二个是间接柱,第三个是目标柱{if (n == 1) {move(ONE, THREE);//如果只有一个盘子,就直接从起始柱到目标柱}else {tower(n - 1, ONE, THREE, TWO);//考虑n-1个盘子如何移动到间接柱,此时实质上间接柱和目标柱关系互换move(ONE, THREE);//将剩下的最大盘子从起始柱移动到目标柱tower(n - 1, TWO, ONE, THREE);//将剩余的小盘子从间接柱移动到目标柱}}int main(){int c = 0;printf("层数为:");scanf("%d", &c);//输入层数tower(c, 'A', 'B', 'C');//调用函数,开始递归printf("次数为:%d", count);//输出次数return 0;}