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;
    }
  • 相关阅读:
    Numpy用于数组的文件输入输出
    numpy利用数组进行数据处理
    numpy的通用函数:快速的元素级数组函数
    NumPy基础知识:数组和矢量计算
    数据处理任务介绍
    Django的ModelForm
    Http1.0和Http1.1的主要区别
    静态库中如何包含资源文件
    zt 正则
    oc调用swift的打包.a / framework 不成功?!
  • 原文地址:https://www.cnblogs.com/waruzhi/p/2545296.html
Copyright © 2011-2022 走看看