zoukankan      html  css  js  c++  java
  • 用格雷码的方法解决汉诺塔问题

      说到汉诺塔问题,首先想到的是最经典的递归解法。今天看到求格雷码的方法,里面提到可以观察格雷码每一次改变的位数和汉诺塔每次移动的盘子的编号,从而产生一种不需要递归和堆栈的汉诺塔解法。

      在生成格雷码的算法中,依次改变的位数是最低位和从右往左数第一个1所在位的左一位,对应汉诺塔的盘子就是最小的盘子和中间某个盘子。最小的盘子有两种可能的移动方案,其他的盘子只有一种可能。对于最小盘子移动到的柱子的解决方法是,根据观察,当盘子总数是奇数时,最小盘子的位置依次是“3->2->1->3->2->1...”;当总数是偶数时,这个顺序是“2->3->1->2->3->1...”。据此从格雷码到汉诺塔的一种对应解决方案就产生了。如下是递归和非递归两种方法的代码。

      

    #include<iostream>
    using namespace std;
    #define MAX 20
    #define YES 1
    #define LOOP 1
    #define FLIP_DIGIT(x) x=((x)=='0'?'1':'0')
    #define FLIP(x) x=(1-(x)) 
    int n;
    void move(int num, int from, int via, int to){
        if(num == 2){
            cout<<from<<"->"<<via<<endl;
            cout<<from<<"->"<<to<<endl;
            cout<<via<<"->"<<to<<endl;
        }
        else{
            move(num-1, from, to, via);
            cout<<from<<"->"<<to<<endl;
            move(num-1, via, from, to);
        }
    }
    int main()
    {
        cin>>n;
        cout<<"This is recursion method"<<endl;
        cout<<"========================="<<endl;
        move(n,1,2,3);
        cout<<"========================="<<endl;
        cout<<"This is gray code method"<<endl;    
        cout<<"========================="<<endl;
        char digit[MAX];
        int position[MAX];
        int i,j;
        for(i = 0; i < MAX; i++){
            digit[i] = '0';
            position[i] = 1;
        }
        int even = YES;
        int circle[3];
        circle[2] = 1;
        if(n % 2 == 0){
            circle[0] = 2;
            circle[1] = 3;
        }
        else{
            circle[0] = 3;
            circle[1] = 2;
        }
        i = 0;
        int m = 0;
        while(LOOP){
            m++;
            if(m > 20)
                break;
            if(even){
                cout<<position[0]<<"->"<<circle[i]<<endl;
                position[0] = circle[i];
                i = (++i)%3;
                FLIP_DIGIT(digit[0]);
            }
            else{
               for(j = 0 ; j < n && digit[j]=='0'; j++)
                    ;
               if(j == n-1){
                    break;
                } 
                FLIP_DIGIT(digit[j+1]);
                cout<<position[j+1]<<"->"<<6-position[j+1]-position[0]<<endl;
                position[j+1] = 6-position[j+1]-position[0];
            }
            FLIP(even);
        }    
        cout<<"========================="<<endl;
        system("pause");
        return 0;
    }
  • 相关阅读:
    将迁移学习用于文本分类 《 Universal Language Model Fine-tuning for Text Classification》
    深度 | 提升深度学习模型的表现,你需要这20个技巧(附论文)
    [线性代数] 矩阵白化
    基于搜索的贝叶斯网络结构学习算法-K2
    Deep learning:四十三(用Hessian Free方法训练Deep Network)
    2020年AI、CV、NLP顶会最全时间表
    浅谈人脸识别中的loss 损失函数
    控制uniFrame显示的一个管理类
    php+sqlserver之如何操作sqlserver数据库
    php支持连接sqlserver数据库
  • 原文地址:https://www.cnblogs.com/waruzhi/p/2545296.html
Copyright © 2011-2022 走看看