递归算法9——复杂递归之汉诺塔问题

汉诺塔问题是源于印度的一个古老传说。上帝创造世界的时候做了三根金刚石柱子,在一根柱子从上往下按照大小顺序摞着64片金属圆盘。上帝命令婆罗门把圆盘从下面开始按照大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间只能移动一个圆盘。

【分析】
这个问题其实就是将n个圆盘从柱子A上移动到柱子C上,在移动过程中可以利用柱子B,每次只能移动一个圆盘,且始终保持大圆盘在下,小圆盘在上。

要把这n个圆盘从柱子A中借助柱子B移动到C中,要先把上面的n-1个盘子从柱子A中借助柱子C移动到B中,然后把第n个圆盘直接移动到柱子C上面,之后再把n-1个圆盘从柱子B借助柱子A移动到C中,这样就把n的问题分解为n-1的问题。

这样即可实现将n个盘子从柱子A移动到柱子C上,但是还有一个问题没有解决,就是怎样才能将n-1个圆盘从A移动到B上,然后再从柱子B移动到柱子C上。

要把n-1个圆盘从柱子A上柱子B上,需要吸纳将上面的n-2个盘子借助B从柱子A移动到柱子C上,然后将第n-1个圆盘直接移动到B上,之后再借助A将n-2个圆盘从C移动到B上。

要将n-1个圆盘从柱子B移动到柱子C还是要借助递归实现。移动圆盘的过程正好符合递归的特点,将较大的问题简化为规模较小的问题,递归结束的条件就是一次只需要移动一个盘子,否则递归将继续进行下去。

为了使问题简化,我们分析一下将3个圆盘从柱子A借助B移动到C上的过程。

(1)将柱子A上的两个圆盘移动到柱子B上(借助柱子C)。
(2)将柱子A上的一个圆盘直接移动到柱子C上(A->C)。
(3)将柱子B上的两个圆盘移动到柱子C上(借助柱子A)。

其中步骤(2)可以直接实现,第(1)步可以继续分解。

a.将柱子A上的一个圆盘直接移动到柱子C上(A->C)。
b.将柱子A上的一个圆盘直接移动到柱子B上(A->B)。
c.将柱子C上的一个圆盘直接移动到柱子B上(C->B)。

第(3)步可以继续分解:

a.将柱子B上的一个圆盘直接移动到柱子A上(B->A)。
b.将柱子B上的一个圆盘直接移动到柱子C上(B->C)。
c.将柱子A上的一个圆盘直接移动到柱子C上(A->C)。

A->C,A->B,C->B,B->A,B->C,A->C

code:

#include<stdio.h>
#include <iostream>
void hanoi(int n, char one, char two, char three);
void move(char x, char y);
void main()
{
	int n;
	printf("请输入圆盘的个数:");
	scanf("%d", &n);
	printf("移动步骤如下:\n");
	hanoi(n, 'A', 'B', 'C');
	system("pause");
}
void move(char x, char y)
{
	printf("%c-->%c\n", x, y);
}
void hanoi(int n, char one, char two, char three)
{
	if (n == 1)
		move(one, three);
	else
	{
		hanoi(n - 1, one, three, two);
		move(one, three);
		hanoi(n - 1, two, one, three);
	}
}


结果:

猜你喜欢

转载自blog.csdn.net/baidu_36669549/article/details/104145360