码迷,mamicode.com
首页 > 移动开发 > 详细

C++学习:任意合法状态下汉诺塔的移动(原创)

时间:2015-08-17 23:21:31      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

汉诺塔问题:

  问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

  现在将问题变形为:初识时,n个金盘分散摆放在三根柱子上,并且所有金盘都处于合法状态,将这些分散的金盘全部移动到第三根柱子上,并打印每一次的移动步骤以及移动后三个柱子上金盘的状态。

  C++实现代码如下:

技术分享
 1 #ifndef _HANOI_H
 2 #define _HANOI_H
 3 #include <iostream>
 4 #include <list>
 5 using namespace std;
 6 class Hanoi{
 7 private:
 8     int plates;                //存放盘子总数;
 9     list<int>* initStatus;    //各个钉子上盘子的个数,存放在一个链表数组中
10 public:
11     Hanoi();
12     Hanoi(int n, int status[]);
13     void ShowHanoi();
14     int arrang(int n);
15     void Move2Last();
16     void Move(int n, int src, int buf, int dest);
17 
18     ~Hanoi();
19 };
20 #endif
Hanoi.h

 

 

技术分享
  1 #include <iostream>
  2 #include <list>
  3 #include <algorithm>
  4 #include "Hanoi.h"
  5 
  6 Hanoi::Hanoi(){
  7     plates = 1;
  8     initStatus = new list<int>[3];
  9     initStatus[0].push_front(0);
 10 }
 11 /*
 12 功能:构造函数,参数status数组是金盘初识状态;参数n是数组长度,也就是金盘个数
 13 说明:    1、status数组中元素必须是0、1或者2
 14         2、数组下标表示金盘编号,对应的元素值表示该金盘所在的柱子编号
 15         3、例如数组[0, 0, 1, 2]表示:3号金盘在2号柱子上;2号金盘在1号柱子上,0号和1号金盘在0号柱子上
 16 */
 17 Hanoi::Hanoi(int n, int status[]){
 18     plates = n;
 19     initStatus = new list<int>[3];
 20     for (int i(0); i<n; i++)
 21         initStatus[status[i]].push_front(i);
 22 }
 23 //显示三根柱子上的金盘状态
 24 void Hanoi::ShowHanoi(){
 25     list<int>::iterator lbegin, lend;
 26     for (int i(0); i<3; i++){
 27         cout << "" << i << "根柱子中金盘从下到上分别是:";
 28         if (initStatus[i].empty()){
 29             cout << "" << endl;
 30         }
 31         else{
 32             lbegin = initStatus[i].begin();
 33             lend = initStatus[i].end();
 34             while (lbegin != lend)
 35                 cout <<   << *lbegin++;
 36             cout << endl;
 37         }
 38     }
 39 }
 40 /*
 41 功能:将0、1、……、n-1号金盘全部移动到n号金盘所在的柱子上
 42 注意1:0、1、……、n-1号金盘已经全部在一根柱子上
 43 注意2:因此,如果要将任意状态下的0—n-1号金盘全部移动到n号金盘所在的柱子上,需要循环调用arrang函数其中参数从0到n循环
 44 */
 45 int Hanoi::arrang(int n){
 46     int src(-1), dest(-1), buf(-1);
 47     for (int i(0); i<3; i++){
 48         list<int>::iterator temp = find(initStatus[i].begin(), initStatus[i].end(), n);
 49         if (temp == initStatus[i].end())
 50             continue;
 51         else{
 52             src = i;
 53             break;
 54         }
 55     }
 56     if (src >= 0){
 57         for (int i(0); i<3; i++){
 58             list<int>::iterator temp = find(initStatus[i].begin(), initStatus[i].end(), n + 1);
 59             if (temp == initStatus[i].end())
 60                 continue;
 61             else{
 62                 dest = i;
 63                 break;
 64             }
 65         }
 66         for (int i(0); i<3; i++){
 67             if (i != src && i != dest){
 68                 buf = i;
 69                 break;
 70             }
 71         }
 72         if (dest >= 0 && src != dest)
 73             Move(n, src, buf, dest);
 74     }
 75     return dest;
 76 }
 77 /*
 78 功能:将三根柱子上的金盘全部移动到2号柱子上,其中金盘初识状态为任意合法状态
 79 注意:必须对三根柱子上的金盘进行初始化,也就是在调用该函数之前必须调用有参构造函数
 80 */
 81 void Hanoi::Move2Last(){
 82     int res;
 83     if (find(initStatus[2].begin(), initStatus[2].end(), plates - 1) != initStatus[2].end())
 84         for (int i(0); i < plates - 1; i++)
 85             res = arrang(i);
 86     else{
 87         int i, little(plates - 2), count(0);
 88         for (i = 0; i<2; i++){
 89             if (find(initStatus[i].begin(), initStatus[i].end(), plates - 1) != initStatus[i].end())
 90                 break;
 91         }
 92         while (find(initStatus[i].begin(), initStatus[i].end(), little) != initStatus[i].end()){
 93             little--;
 94             count++;
 95         }
 96         if (little<0){
 97             Move(plates, i, 1 - i, 2);
 98             return;
 99         }
100         for (int j(0); j<little; j++)
101             arrang(j);
102         int buf(1 - i), dest(2);
103         while (count--){
104             initStatus[i].remove(little+1);
105             initStatus[dest].push_back(little+1);
106             cout << "" << little+1 << "号金盘从" << i << "号柱子移动到" << dest << "号柱子:" << endl;
107             ShowHanoi();
108             Move(little, buf, i, dest);
109             int temp = buf;
110             buf = dest;
111             dest = temp;
112             little++;
113         }
114         if (dest == 1-i)
115             Move(little, buf, i, dest);
116         initStatus[i].remove(plates - 1);
117         initStatus[2].push_back(plates - 1);
118         cout << "" << plates << "号金盘从" << i << "号柱子移动到" << 2 << "号柱子:" << endl;
119         ShowHanoi();
120         Move(little, 1 - i, i, 2);
121     }
122     /*
123     //下面代码也能实现将任意合法状态的金盘,全部移动到第三根柱子上,但是效率较低
124     for(int i(0); i < plates-1; i++)
125     res = arrang(i);
126     if(res == 2)
127     return;
128     else if(res == 1)
129     Move(plates-1, res, 0, 2);
130     else
131     Move(plates-1, res, 1, 2);
132     */
133 }
134 /*
135 功能:将src号柱子中的0、1、……、n号金盘以buf为中间缓存,全部移动到dest号柱子上
136 注意:src号柱子上0—n号金盘必须是连续的
137 */
138 void Hanoi::Move(int n, int src, int buf, int dest){
139     if (n >= 0){
140         Move(n - 1, src, dest, buf);
141         initStatus[src].remove(n);
142         initStatus[dest].push_back(n);
143         cout << "" << n << "号金盘从" << src << "号柱子移动到" << dest << "号柱子:" << endl;
144         ShowHanoi();
145         Move(n - 1, buf, src, dest);
146     }
147 }
148 Hanoi::~Hanoi(){
149     delete[]initStatus;
150 }
Hanoi.cpp

 

技术分享
 1 #include <iostream>
 2 #include "Hanoi.h"
 3 using namespace std;
 4 void main(){
 5     int a[4] = { 0, 1, 1, 1 };
 6     Hanoi myhanoi(4, a);
 7     myhanoi.ShowHanoi();
 8     myhanoi.Move2Last();
 9     system("pause");
10 }
测试代码

 

C++学习:任意合法状态下汉诺塔的移动(原创)

标签:

原文地址:http://www.cnblogs.com/scorpion-zs/p/4737983.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!