1.6 用栈来求解汉诺塔问题

匿名 (未验证) 提交于 2019-12-03 00:33:02

题目:汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。求当塔有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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!