1.6 用栈来求解汉诺塔问题

Posted latup

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.6 用栈来求解汉诺塔问题相关的知识,希望对你有一定的参考价值。

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

 

以上是关于1.6 用栈来求解汉诺塔问题的主要内容,如果未能解决你的问题,请参考以下文章

左神算法书籍《程序员代码面试指南》——1_06用栈来求解汉诺塔问题

用栈来求解汉诺塔问题

Hanoi(汉诺塔问题)用栈来求解

算法题06-用栈来解决汉诺塔问题

用栈模拟汉诺塔问题

数据结构与算法之深入解析汉诺塔问题的求解思路与算法示例