题解 | #用栈来求解汉诺塔问题#
用栈来求解汉诺塔问题
https://www.nowcoder.com/practice/1a2f618b3433487295657b3414f4e7c4
递归方法
思路
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; }