zoukankan      html  css  js  c++  java
  • 汉诺塔


    一、问题描述

    在三根柱子之间一次只能移动一个圆盘,在小圆盘上不能放大圆盘。

    二、算法分析

    依据分治的策略,将问题化简为两个圆盘,三根柱子 A、B、C,首先解决倒数第二个圆盘的移动,将 n - 1(小盘) 从 A 移到 B,然后将 n(大盘) 从 A 移到 C,再将小盘从 B 移到 C。

    子问题分别为:小盘和大盘的移动

    三、代码实现

    #include <stdio.h>
    #include <stdlib.h>
    
    #define num  5
    
    static int a[num] = { 1, 2, 3, 4, 5 };  // 1 - 最小的物品    5 - 最大的物品
    static int b[num] = { 0 };  // 0 - 为空
    static int c[num] = { 0 };  // 0 - 为空
    static int idxA = 0; // 当前有物品的下标
    static int idxB = num;
    static int idxC = num;
    
    /// 定义 move 函数,移动物品
    void move(char from, char to)
    {
        int x = 0;
        
        printf("%c -> %c
    ", from, to);
    
        // 移出
        if (from == 'A' && idxA > -1 && idxA < num) {
            x = a[idxA];
            a[idxA] = 0;
            idxA++;
        }
        else if (from == 'B' && idxB > -1 && idxB < num) {
            x = b[idxB];
            b[idxB] = 0;
            idxB++;
        }
        else if (from == 'C' && idxC > -1 && idxC < num) {
            x = c[idxC];
            c[idxC] = 0;
            idxC++;
        }
        else {
            printf("%c from 数组越界!", from);
            return;
        }
        
        // 存入
        if (to == 'A' && --idxA > -1 && idxA < num) {
            a[idxA] = x;
        }
        else if (to == 'B' && --idxB > -1 && idxB < num) {
            b[idxB] = x;
        }
        else if (to == 'C' && --idxC > -1 && idxC < num){
            c[idxC] = x;
        }
        else {
            printf("%c to 数组越界!", to);
            return;
        }
        
        // 打印移动后结果
        for (int i = 0; i < num; i++) {
            printf("%d      %d      %d
    ", a[i], b[i], c[i]);
        }
        printf("
    ");
    }
    
    /// 将 n 个物品从 one 座借助 two 座,移到 three 座
    void hanoi(int n, char one, char two, char three)
    {
        if(n == 1) {
            move(one, three); // 只有一个物品,直接移动
        }
        else {
            hanoi(n-1, one, three, two); //首先把 n - 1 个从 one 移动到 two
            move(one, three); // 然后把最后一个 n 从 one 移动到 three
            hanoi(n-1, two, one, three); // 最后再把 n - 1 个从 two 移动到 three
        }
    }
    
    int main()
    {
        hanoi(num, 'A', 'B', 'C');
        
        return 0;
    }
    
    A -> C
    0      0      0
    2      0      0
    3      0      0
    4      0      0
    5      0      1
    
    A -> B
    0      0      0
    0      0      0
    3      0      0
    4      0      0
    5      2      1
    
    C -> B
    0      0      0
    0      0      0
    3      0      0
    4      1      0
    5      2      0
    
    A -> C
    0      0      0
    0      0      0
    0      0      0
    4      1      0
    5      2      3
    
    B -> A
    0      0      0
    0      0      0
    1      0      0
    4      0      0
    5      2      3
    
    B -> C
    0      0      0
    0      0      0
    1      0      0
    4      0      2
    5      0      3
    
    A -> C
    0      0      0
    0      0      0
    0      0      1
    4      0      2
    5      0      3
    
    A -> B
    0      0      0
    0      0      0
    0      0      1
    0      0      2
    5      4      3
    
    C -> B
    0      0      0
    0      0      0
    0      0      0
    0      1      2
    5      4      3
    
    C -> A
    0      0      0
    0      0      0
    0      0      0
    2      1      0
    5      4      3
    
    B -> A
    0      0      0
    0      0      0
    1      0      0
    2      0      0
    5      4      3
    
    C -> B
    0      0      0
    0      0      0
    1      0      0
    2      3      0
    5      4      0
    
    A -> C
    0      0      0
    0      0      0
    0      0      0
    2      3      0
    5      4      1
    
    A -> B
    0      0      0
    0      0      0
    0      2      0
    0      3      0
    5      4      1
    
    C -> B
    0      0      0
    0      1      0
    0      2      0
    0      3      0
    5      4      0
    
    A -> C
    0      0      0
    0      1      0
    0      2      0
    0      3      0
    0      4      5
    
    B -> A
    0      0      0
    0      0      0
    0      2      0
    0      3      0
    1      4      5
    
    B -> C
    0      0      0
    0      0      0
    0      0      0
    0      3      2
    1      4      5
    
    A -> C
    0      0      0
    0      0      0
    0      0      1
    0      3      2
    0      4      5
    
    B -> A
    0      0      0
    0      0      0
    0      0      1
    0      0      2
    3      4      5
    
    C -> B
    0      0      0
    0      0      0
    0      0      0
    0      1      2
    3      4      5
    
    C -> A
    0      0      0
    0      0      0
    0      0      0
    2      1      0
    3      4      5
    
    B -> A
    0      0      0
    0      0      0
    1      0      0
    2      0      0
    3      4      5
    
    B -> C
    0      0      0
    0      0      0
    1      0      0
    2      0      4
    3      0      5
    
    A -> C
    0      0      0
    0      0      0
    0      0      1
    2      0      4
    3      0      5
    
    A -> B
    0      0      0
    0      0      0
    0      0      1
    0      0      4
    3      2      5
    
    C -> B
    0      0      0
    0      0      0
    0      0      0
    0      1      4
    3      2      5
    
    A -> C
    0      0      0
    0      0      0
    0      0      3
    0      1      4
    0      2      5
    
    B -> A
    0      0      0
    0      0      0
    0      0      3
    0      0      4
    1      2      5
    
    B -> C
    0      0      0
    0      0      2
    0      0      3
    0      0      4
    1      0      5
    
    A -> C
    0      0      1
    0      0      2
    0      0      3
    0      0      4
    0      0      5
    

    四、内容来源

    汉诺塔

  • 相关阅读:
    Luogu P1090 合并果子(优先队列 || priority_queue)
    Luogu P1012 拼数
    hibernate5.2的基本配置
    [bzoj1210][HNOI2004]邮递员【插头dp】
    [bzoj3470]Freda’s Walk【概率与期望dp】
    [bzoj4851][Jsoi2016]位运算【矩阵乘法】【状压dp】
    [bzoj4852][Jsoi2016]炸弹攻击【随机化】
    [bzoj4853][Jsoi2016]飞机调度【最短路】【网络流】
    [bzoj4850][Jsoi2016]灯塔【暴力】
    [bzoj4919][Lydsy1706月赛]大根堆【dp】【启发式合并】【stl】
  • 原文地址:https://www.cnblogs.com/dins/p/hanoi.html
Copyright © 2011-2022 走看看