zoukankan      html  css  js  c++  java
  • 四个柱子的汉诺塔

    和三个柱子的最初的汉诺塔很类似,只是多了一个柱子,相当于缓存区大了一些,处理的速度自然快了一些。

    粗略的C代码(并没有使先移动到第四根柱子上面的圆盘的数量是最优):

    #include <stdio.h>
    
    int count = 0;
    
    void hanoi (char s, char t1, char t2, char t, int n)
    {
        if (0 == n)
            return;
        if (1 == n)
        {
            printf ("%c -> %c
    ", s, t);
            printf("%d
    ", ++count);
            return;
        }
    
        hanoi (s, t2, t, t1, n - 2); // 先将 n - 2 个圆盘从 s 移动到 t1
        printf ("%c -> %c
    ", s, t2); // 将此时最上面的圆盘移动到 t2 上
        printf("%d
    ", ++count);
        printf ("%c -> %c
    ", s, t); // 将剩下的最后一个圆盘移动到 t 上
        printf("%d
    ", ++count);
        printf ("%c -> %c
    ", t2, t); // 将 t2 上的圆盘移动到 t 上
        printf("%d
    ", ++count);
        hanoi (t1, s, t2, t, n - 2); // 将 t1 上的圆盘移动到 t上,此时,s 和 t2 成了辅助的柱子
    
        return;
    }
    
    int main ()
    {
    
        hanoi ('A', 'B', 'C', 'D', 8);
        return (0);
    
    }
    

    这个版本就是简单地先将 n - 2 个圆盘放到第 4 个柱子上,然后将剩下的两个圆盘转移到目标柱子上,如此递归。所以并不是最优解。

    关于对于不同的圆盘的数量,如何控制率先移动到第四个柱子的圆盘的数量,目前只是想到了一种很笨的方法,就是遍历所有的可能,然后找出最优解,然后存储到数组中,然后再再递归调用移动圆盘的函数的时候进行控制(移动圆盘的函数暂时还没有实现)。

    由于样本数据取到了64个圆盘,最后的数据会比较大,所以选择了不限数据大小的Python,进行确定四个柱子的情况下的最少移动的次数和最优的率先移动到第 4 根柱子的圆盘的数量。

    Python代码:

    # 最终只在列表中存储64个数据,第一个数据舍弃,是为了序列能够从1开始
    
    # 存储三个柱子的情况,然后初始化
    ThreeHanoi = []
    ThreeHanoi.append(0)
    ThreeHanoi.append(1)
    for i in range(2, 65): # 只需要再添加 63 个数据,就凑足了 65 了数据,实际有效的数据只有64个,第一个数据只是为了占位
        ThreeHanoi.append(2 * ThreeHanoi[i - 1] + 1)
    
    # 存储四个柱子的情况,然后初始化
    count4 = 0
    FourHanoi = []
    FourHanoi.append(0) # 占位
    FourHanoi.append(1) # 只有一个圆盘需要移动 1 次
    FourHanoi.append(3) # 有两个圆盘的情况下需要移动 3 次
    StoreJ = []
    StoreJ.append(0)
    StoreJ.append(0)
    StoreJ.append(0)
    for i in range(3, 65): # 还需要再添加 62 个数据
        min = ThreeHanoi[i]
        flag_j = 0
        for j in range(1, i):
            count4 = 2 * FourHanoi[j] + ThreeHanoi[i - j]
            if count4 < min:
                min = count4
                flag_j = j
        FourHanoi.append(min)
        StoreJ.append(flag_j)
    
    print(ThreeHanoi)
    print(FourHanoi)
    print(StoreJ)
    

    结果:

    [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647, 4294967295, 8589934591, 17179869183, 34359738367, 68719476735, 137438953471, 274877906943, 549755813887, 1099511627775, 2199023255551, 4398046511103, 8796093022207, 17592186044415, 35184372088831, 70368744177663, 140737488355327, 281474976710655, 562949953421311, 1125899906842623, 2251799813685247, 4503599627370495, 9007199254740991, 18014398509481983, 36028797018963967, 72057594037927935, 144115188075855871, 288230376151711743, 576460752303423487, 1152921504606846975, 2305843009213693951, 4611686018427387903, 9223372036854775807, 18446744073709551615]
    [0, 1, 3, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 129, 161, 193, 225, 257, 289, 321, 385, 449, 513, 577, 641, 705, 769, 897, 1025, 1153, 1281, 1409, 1537, 1665, 1793, 2049, 2305, 2561, 2817, 3073, 3329, 3585, 3841, 4097, 4609, 5121, 5633, 6145, 6657, 7169, 7681, 8193, 8705, 9217, 10241, 11265, 12289, 13313, 14337, 15361, 16385, 17409, 18433]
    [0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, 25, 26, 27, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 53]
    

    为方便观察,下面将数据以“盘数 : 最少移动次数,最合适的率先移动的盘数”列出:

    1  :  1 ,  0
    2  :  3 ,  0
    3  :  5 ,  1
    4  :  9 ,  1
    5  :  13 ,  2
    6  :  17 ,  3
    7  :  25 ,  3
    8  :  33 ,  4
    9  :  41 ,  5
    10  :  49 ,  6
    11  :  65 ,  6
    12  :  81 ,  7
    13  :  97 ,  8
    14  :  113 ,  9
    15  :  129 ,  10
    16  :  161 ,  10
    17  :  193 ,  11
    18  :  225 ,  12
    19  :  257 ,  13
    20  :  289 ,  14
    21  :  321 ,  15
    22  :  385 ,  15
    23  :  449 ,  16
    24  :  513 ,  17
    25  :  577 ,  18
    26  :  641 ,  19
    27  :  705 ,  20
    28  :  769 ,  21
    29  :  897 ,  21
    30  :  1025 ,  22
    31  :  1153 ,  23
    32  :  1281 ,  24
    33  :  1409 ,  25
    34  :  1537 ,  26
    35  :  1665 ,  27
    36  :  1793 ,  28
    37  :  2049 ,  28
    38  :  2305 ,  29
    39  :  2561 ,  30
    40  :  2817 ,  31
    41  :  3073 ,  32
    42  :  3329 ,  33
    43  :  3585 ,  34
    44  :  3841 ,  35
    45  :  4097 ,  36
    46  :  4609 ,  36
    47  :  5121 ,  37
    48  :  5633 ,  38
    49  :  6145 ,  39
    50  :  6657 ,  40
    51  :  7169 ,  41
    52  :  7681 ,  42
    53  :  8193 ,  43
    54  :  8705 ,  44
    55  :  9217 ,  45
    56  :  10241 ,  45
    57  :  11265 ,  46
    58  :  12289 ,  47
    59  :  13313 ,  48
    60  :  14337 ,  49
    61  :  15361 ,  50
    62  :  16385 ,  51
    63  :  17409 ,  52
    64  :  18433 ,  53
    

    这三行数据依次是三个柱子时的最少移动次数,四个柱子的最少移动次数和四个柱子时率先移动到第四根柱子的最优数量。

  • 相关阅读:
    [置顶] Windows Phone后台音乐详解一
    Android应用开发学习笔记之BroadcastReceiver
    二维码闪电登录流程详解,附demo(1/2)
    C#利用Lambda和Expression实现数据的动态绑定
    从M个数中随机选出N个数的所有组合,有序,(二)
    3DShader之立方体环境映射(cubic environment mapping)
    二维码闪电登录流程详解,附demo(2/2)
    oracle 分区表exchange原理
    禁止页面复制功能 js禁止复制 禁用页面右键菜单
    sleep与信号唤醒的问题 & 内核对信号的处理方式
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/13645005.html
Copyright © 2011-2022 走看看