汉诺塔
一、问题描述
在三根柱子之间一次只能移动一个圆盘,在小圆盘上不能放大圆盘。
二、算法分析
依据分治的策略,将问题化简为两个圆盘,三根柱子 A、B、C,首先解决倒数第二个圆盘的移动,将 n - 1(小盘) 从 A 移到 B,然后将 n(大盘) 从 A 移到 C,再将小盘从 B 移到 C。
子问题分别为:小盘和大盘的移动。
三、代码实现
#include <stdio.h>
#include <stdlib.h>
#define num 5
static int a[num] = { 1, 2, 3, 4, 5 }; // 1 - 最小的物品 5 - 最大的物品
static int b[num] = { 0 }; // 0 - 为空
static int c[num] = { 0 }; // 0 - 为空
static int idxA = 0; // 当前有物品的下标
static int idxB = num;
static int idxC = num;
/// 定义 move 函数,移动物品
void move(char from, char to)
{
int x = 0;
printf("%c -> %c\n", from, to);
// 移出
if (from == 'A' && idxA > -1 && idxA < num) {
x = a[idxA];
a[idxA] = 0;
idxA++;
}
else if (from == 'B' && idxB > -1 && idxB < num) {
x = b[idxB];
b[idxB] = 0;
idxB++;
}
else if (from == 'C' && idxC > -1 && idxC < num) {
x = c[idxC];
c[idxC] = 0;
idxC++;
}
else {
printf("%c from 数组越界!", from);
return;
}
// 存入
if (to == 'A' && --idxA > -1 && idxA < num) {
a[idxA] = x;
}
else if (to == 'B' && --idxB > -1 && idxB < num) {
b[idxB] = x;
}
else if (to == 'C' && --idxC > -1 && idxC < num){
c[idxC] = x;
}
else {
printf("%c to 数组越界!", to);
return;
}
// 打印移动后结果
for (int i = 0; i < num; i++) {
printf("%d %d %d\n", a[i], b[i], c[i]);
}
printf("\n");
}
/// 将 n 个物品从 one 座借助 two 座,移到 three 座
void hanoi(int n, char one, char two, char three)
{
if(n == 1) {
move(one, three); // 只有一个物品,直接移动
}
else {
hanoi(n-1, one, three, two); //首先把 n - 1 个从 one 移动到 two
move(one, three); // 然后把最后一个 n 从 one 移动到 three
hanoi(n-1, two, one, three); // 最后再把 n - 1 个从 two 移动到 three
}
}
int main()
{
hanoi(num, 'A', 'B', 'C');
return 0;
}
A -> C
0 0 0
2 0 0
3 0 0
4 0 0
5 0 1
A -> B
0 0 0
0 0 0
3 0 0
4 0 0
5 2 1
C -> B
0 0 0
0 0 0
3 0 0
4 1 0
5 2 0
A -> C
0 0 0
0 0 0
0 0 0
4 1 0
5 2 3
B -> A
0 0 0
0 0 0
1 0 0
4 0 0
5 2 3
B -> C
0 0 0
0 0 0
1 0 0
4 0 2
5 0 3
A -> C
0 0 0
0 0 0
0 0 1
4 0 2
5 0 3
A -> B
0 0 0
0 0 0
0 0 1
0 0 2
5 4 3
C -> B
0 0 0
0 0 0
0 0 0
0 1 2
5 4 3
C -> A
0 0 0
0 0 0
0 0 0
2 1 0
5 4 3
B -> A
0 0 0
0 0 0
1 0 0
2 0 0
5 4 3
C -> B
0 0 0
0 0 0
1 0 0
2 3 0
5 4 0
A -> C
0 0 0
0 0 0
0 0 0
2 3 0
5 4 1
A -> B
0 0 0
0 0 0
0 2 0
0 3 0
5 4 1
C -> B
0 0 0
0 1 0
0 2 0
0 3 0
5 4 0
A -> C
0 0 0
0 1 0
0 2 0
0 3 0
0 4 5
B -> A
0 0 0
0 0 0
0 2 0
0 3 0
1 4 5
B -> C
0 0 0
0 0 0
0 0 0
0 3 2
1 4 5
A -> C
0 0 0
0 0 0
0 0 1
0 3 2
0 4 5
B -> A
0 0 0
0 0 0
0 0 1
0 0 2
3 4 5
C -> B
0 0 0
0 0 0
0 0 0
0 1 2
3 4 5
C -> A
0 0 0
0 0 0
0 0 0
2 1 0
3 4 5
B -> A
0 0 0
0 0 0
1 0 0
2 0 0
3 4 5
B -> C
0 0 0
0 0 0
1 0 0
2 0 4
3 0 5
A -> C
0 0 0
0 0 0
0 0 1
2 0 4
3 0 5
A -> B
0 0 0
0 0 0
0 0 1
0 0 4
3 2 5
C -> B
0 0 0
0 0 0
0 0 0
0 1 4
3 2 5
A -> C
0 0 0
0 0 0
0 0 3
0 1 4
0 2 5
B -> A
0 0 0
0 0 0
0 0 3
0 0 4
1 2 5
B -> C
0 0 0
0 0 2
0 0 3
0 0 4
1 0 5
A -> C
0 0 1
0 0 2
0 0 3
0 0 4
0 0 5