题目:汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。求当塔有N层的时候,打印最优移动过程和最优移动总步数。
例如,当塔数为两层时,最上层的塔记为1, 最下层的塔记为2,则打印:
Move 1 from left to mid
Move 1 from mid to right
Move 2 from left to mid
Move 1 from right to mid
Move 1 from mid to left
Move 2 from mid to right
Move 1 from left to mid
Move 1 from mid to right
要求:
用以下两种方法解决:
方法一:递归的方法;
方法二:非递归的方法,用栈来模拟汉诺塔的三个塔。
方法一:递归的方法
1 //用栈来求解汉诺塔问题 2 3 #include <iostream> 4 #include <string> 5 6 using namespace std; 7 8 int process(int num, string left, string mid, string right, string from, string to) 9 { 10 if (num == 1) 11 { 12 if ((from.compare(mid) == 0) || (to.compare(mid) == 0)) 13 { 14 cout << "Move 1 from " << from << " to " << to << endl; 15 return 1; 16 } 17 else 18 { 19 cout << "Move 1 from " << from << " to " << mid << endl; 20 cout << "Move 1 from " << mid << " to " << to << endl; 21 return 2; 22 } 23 } 24 if ((from.compare(mid) == 0) || (to.compare(mid) == 0)) //处理将所有圆盘从“左”->“中”、“中”->“左”、“中”->“右”、“右”->“中”等情况 25 { 26 string another = ((from.compare(left) == 0) || (to.compare(left) == 0)) ? right : left; 27 int part1 = process(num - 1, left, mid, right, from, another); 28 int part2 = 1; 29 cout << "Move " << num << " from " << from << " to " << to << endl; 30 int part3 = process(num - 1, left, mid, right, another, to); 31 return part1 + part2 + part3; 32 } 33 else 34 { 35 int part1 = process(num - 1, left, mid, right, from, to); //处理前N - 1个圆盘,从“from”到“to” 36 int part2 = 1; 37 cout << "Move " << num << " from " << from << " to " << mid << endl; //处理第N个圆盘,从“from”到“mid” 38 int part3 = process(num - 1, left, mid, right, to, from); //处理前N - 1个圆盘,从“to”到“from” 39 int part4 = 1; 40 cout << "Move " << num << " from " << mid << " to " << to << endl; //处理第N个圆盘,从“mid”到“to” 41 int part5 = process(num - 1, left, mid, right, from, to); //处理前N - 1个圆盘,从“from”到“to” 42 return part1 + part2 + part3 + part4 + part5; //返回该次调用移动了多少步 43 } 44 } 45 46 int hanoiProblem1(int num, string left, string mid, string right) 47 { 48 if (num < 1) 49 { 50 return 0; 51 } 52 return process(num, left, mid, right, left, right); 53 }
方法二:非递归的方法
1 enum Action {No, LToM, MToL, MToR, RToM}; 2 3 static int fStackTotStack(Action &record, Action preNoAct, Action nowAct, stack<int> &fStack, stack<int> &tStack, string from, string to) 4 { 5 if (record != preNoAct && fStack.top() < tStack.top()) 6 { 7 tStack.push(fStack.top()); 8 fStack.pop(); 9 cout << "Move " << tStack.top() << " from " << from << " to " << to << endl; 10 record = nowAct; 11 return 1; 12 } 13 return 0; 14 } 15 16 int hanoiProblem2(int num, string left, string mid, string right) 17 { 18 stack<int> lS; 19 stack<int> mS; 20 stack<int> rS; 21 lS.push(INT_MAX); 22 mS.push(INT_MAX); 23 rS.push(INT_MAX); 24 for (int i = num; i > 0; i--) 25 { 26 lS.push(i); 27 } 28 Action record = No; 29 30 int step = 0; 31 while(rS.size() != num + 1) 32 { 33 step += fStackTotStack(record, MToL, LToM, lS, mS, left, mid); //“左”->“中” 34 step += fStackTotStack(record, LToM, MToL, mS, lS, mid, left); //“中”->“左” 35 step += fStackTotStack(record, RToM, MToR, mS, rS, mid, right); //“中”->“右” 36 step += fStackTotStack(record, MToR, RToM, rS, mS, right, mid); //“右”->“中” 37 } 38 39 return step; 40 }
原文地址:https://www.cnblogs.com/latup/p/9035267.html
时间: 2024-11-06 05:22:45