栈解决汉诺塔问题
汉诺塔问题比较经典,这里修改--下游戏规则:
- 现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。
- 求当塔有N层的时候,打印最优移动过程和最优移动总步数。
- 在走出最少步数过程中的任何时刻,四个动作中只有一个动作不违反小压大和相邻不可逆原则(相邻的两次操作不互为逆操作如:MtoR和RtoM),另外三个动作一定都会违反。
#include <iostream> #include <stack> using namespace std; enum Act { // 利用绝对值解决逆操作问题 感谢Stan提供的思路 No = 0, LtoM = 1, MtoL = -1, RtoM = 2, MtoR = -2 }; int move(Act& reAct, Act nowAct, stack<int>& src, stack<int>& dst) { if (!src.empty() && (abs(reAct) != abs(nowAct)) && (dst.empty() || src.top() < dst.top())) { dst.push(src.top()); src.pop(); switch (nowAct){ case 1: cout << "Move " << dst.top() << " from L to M" << endl; break; case -1: cout << "Move " << dst.top() << " from M to L" << endl; break; case 2: cout << "Move " << dst.top() << " from R to M" << endl; break; case -2: cout << "Move " << dst.top() << " from M to R" << endl; break; } reAct = nowAct; return 1; } return 0; } int solveHanoi(int l) { // 解决从左往右移动的问题 stack<int> lS, mS, rS; for (int i = l; i > 0; i--) // 修改此处可决定源栈 { lS.push(i); } Act record = No; int step = 0; while (rS.size() != l) // 修改此处可决定目的栈 { step += move(record, LtoM, lS, mS); step += move(record, MtoL, mS, lS); step += move(record, RtoM, rS, mS); step += move(record, MtoR, mS, rS); } return step; } int main() { cout << "Solve 3 Hanoi LtoR:" << endl; cout << "I will move " << solveHanoi(3) << " steps" << endl; return 0; }