递归方法
思路
1. 终止条件
当只剩最上层塔需要移动时,需要考虑两种情况:
- 从中间塔来,或者去中间塔,这时只需一步;
- 从左到右或者从右到左,分两步;
2. 多层塔情况
不止一层塔需要移动,通过递归实现上面塔先移开,也是需要考虑上述两种情况。
- 当起点或终点为mid。需要先把上面塔从from移动到另一边another。待最后一层塔从from到to后,再把上面塔从another移动到to。
- 起点或终点不为mid。需要经过mid。
代码
#include<iostream>
using namespace std;
void moveTo(int n, string& from, string& to) {
cout << "Move " << n << " from " << from << " to " << to << endl;
}
// 返回所需的步数
int process(int n, string& left, string& mid, string& right, string& from,
string& to) {
// 最上层塔需要移动时
if (n == 1) {
// 从中间塔来,或者去中间塔
if (from == mid || to == mid) {
moveTo(n, from, to);
//这一步步数为1
return 1;
} else {
// 从左到右或者从右到左,分两步
// 这两步也保证了下面的递归函数可以直接写from到to,而无需先from到mid,再到to.
moveTo(n, from, mid);
moveTo(n, mid, to);
return 2;
}
} else {
// 不止一层塔需要移动,通过递归实现上面塔先移开
// 起点或终点为mid
if (from == mid || to == mid) {
//先把上面塔从from移动到另一边another
string another = (from == left || to == left) ? right : left;
int part1 = process(n - 1, left, mid, right, from, another);
// 由于是移动到中间塔或者从中间塔移动到两边,所以步数为1
int part2 = 1;
moveTo(n, from, to);
// 再把上面塔从another移动到to
int part3 = process(n - 1, left, mid, right, another, to);
// 返回上面三步的总步数
return part1 + part2 + part3;
} else {
// 起点或终点不为mid
// 1. 将上面塔从from移动到to
int part1 = process(n - 1, left, mid, right, from, to);
// 2. 将第n层塔从from移动到mid
moveTo(n, from, mid);
int part2 = 1;
// 3. 将上面塔从to移动到from
int part3 = process(n - 1, left, mid, right, to, from);
// 4. 将第n层塔从mid移动到to
moveTo(n, mid, to);
int part4 = 1;
// 5. 将上面塔从from移动到to
int part5 = process(n - 1, left, mid, right, from, to);
return part1 + part2 + part3 + part4 + part5;
}
}
}
// 返回最优总步数
int hanoi(int n, string& left, string& mid, string& right) {
if (n < 1) {
return 0;
}
return process(n, left, mid, right, left, right);
}
int main() {
int N;
cin >> N;
string left = "left", mid = "mid", right = "right";
int allStep = hanoi(N, left, mid, right);
cout << "It will move " << allStep << " steps." << endl;
}

京公网安备 11010502036488号