汉诺塔
2024年11月15日大约 3 分钟教学文档递归分治法
汉诺塔问题解答
题目描述
汉诺塔是一个古老的数学问题:有三根杆子 A,B,C。A杆上有 N个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C杆:
- 每次只能移动一个圆盘
- 大盘不能叠在小盘上面
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
解题思路
递归基础情况:当只有一个圆盘(n==1)时,直接将其从源塔座x移动到目标塔座z,并增加步骤计数器sum。如果此时sum等于用户指定的目标步骤数m,则输出该步骤的信息。
递归步骤:
- 首先,将上面的n-1个圆盘视为一个整体,通过目标塔座z的辅助,将它们从源塔座x移动到辅助塔座y。
- 然后,将剩下的最大圆盘(第n个)从源塔座x移动到目标塔座z,并增加步骤计数器sum。如果此时sum等于m,则输出该步骤的信息。
- 最后,将之前移动到辅助塔座y的n-1个圆盘整体,通过源塔座x的辅助,移动到目标塔座z。
全局变量:使用全局变量sum来跟踪已经执行的步骤数,以及全局变量m来存储用户希望查看的步骤数。
输出:在递归结束后,输出完成汉诺塔所需的总步骤数sum。
具体代码实现
#include <iostream>
using namespace std;
// 全局变量
int sum = 0, m;
// 递归函数
void hanoi(char x, char y, char z, int n) {
if (n == 1) { // 递归基础情况
sum++; // 增加步骤数
if (sum == m) { // 如果当前步骤是用户指定的步骤
cout << "#" << n << ": " << x << "->" << z << endl; // 输出步骤信息
}
} else { // 递归步骤
hanoi(x, z, y, n - 1); // 将n-1个圆盘从x移动到y,z作为辅助
sum++; // 增加步骤数
if (sum == m) { // 如果当前步骤是用户指定的步骤
cout << "#" << n << ": " << x << "->" << z << endl; // 输出步骤信息(注意:这里输出的是最大圆盘的移动)
}
hanoi(y, x, z, n - 1); // 将n-1个圆盘从y移动到z,x作为辅助
}
}
int main() {
int n; // 圆盘数量
cin >> n >> m; // 输入圆盘数量和用户希望查看的步骤数
hanoi('A', 'B', 'C', n); // 执行汉诺塔操作
cout << sum << endl; // 输出完成汉诺塔所需的总步骤数
return 0;
}
注意
- 本代码中的
#include <bits/stdc++.h>被替换为标准的#include <iostream>,因为前者不是标准C++库,且在部分编译环境中可能不被支持。 - 确保输入了合理的
n和m值,其中n表示圆盘数量,m表示用户希望查看的特定步骤编号(如果不需要查看特定步骤,可忽略此参数或设置为一个大于总步骤数的值)。
