问题引入
“双色河内塔”由“河内之塔”的规则衍生而来(点击查看),区别在于双色河内塔的目的是将图1所示的圆盘位置,移动成为图2所示的圆盘位置。
图1
图2
问题分析
“双色河内塔”最初在一根柱子上有两种颜色的圆盘从小到大交替排列,我们要进行的操作就是将两种颜色的圆环盘出来,然后放到两根柱子上,并且是从小到大放置,等同于“汉诺塔”问题。
“双色河内塔”解法与“河内塔(单色)”类似,我们同样要进行“递回”,但是略有不同。
先看只有两个盘的情况, 只要将第一柱的黄色移动至第二柱,而接下来第一柱的蓝色移动至第三柱,即完成了圆盘的移动,如下图。
接下来我们看四个盘的情况,两种颜色交替,一大一小。首先必须用递回完成下图第一个图到第二个图的移动,接下来最底层的就不用管它们了,因为它们已经就定位,只要再处理第一柱的上面两个盘子即可,如下图。
紧接着我们看六个盘的情况,也是两种颜色交叉排列,从小到大。同样的,我们仍然是先利用“递回”的方法完成下图第一个图片到第二个图片的移动,接下来最底层的就不用管它们了,因为它们已经就定位。之后,我们只要再处理第一柱上面的四个盘子就 可以了,这又与之前只有四盘的情况相同。如下图。
接下来,如果是八盘、十盘、十二盘等……,不难看出,解题的方法观念相同,只是“递回”的次数不同。
代码实现
对问题进行了分析,那么如何编写程序呢?最主要的问题是实现“递回”,代码如下所示。
(采用的语言为C语言,编译环境为DevC++。)
//导入头文件
#include <stdio.h>
//借助递归思想进行递回-移动
void hanoi(int disks, char source, char temp, char target){
if (disks == 1){
printf("move disk from %c to %c\n", source, target);
printf("move disk from %c to %c\n", source, target);
}else {
hanoi(disks-1, source, target, temp);
hanoi(1, source, temp, target);
hanoi(disks-1, temp, source, target);
}
}
//使用A\B\C 表示柱子
void hanoi2colors(int disks){
char source = 'A';
char temp = 'B';
char target = 'C';
int i;
for(i = disks / 2; i > 1; i--){
hanoi(i-1, source, temp, target);
printf("move disk from %c to %c\n", source, temp);
printf("move disk from %c to %c\n", source, temp);
hanoi(i-1, target, temp, source);
printf("move disk from %c to %c\n", temp, target);
}
printf("move disk from %c to %c\n", source, temp);
printf("move disk from %c to %c\n", source, target);
}
//主函数
int main(){
int n;
printf("请输入盘数:");
scanf("%d", &n);
hanoi2colors(n);
return 0;
}
运行结果
写在最后:
读两遍下来,如果仍然有不清楚的地方,可在评论区留言。
如果你有其他感到困惑的问题,欢迎留言。