繁体   English   中英

Python中四塔的河内塔递归算法

[英]Tower of Hanoi recursive algorithm for four towers in Python

我在为 python 中的四个凳子实现河内塔游戏的最佳算法时遇到了相当多的麻烦。

首先,在课堂上我们解决了三座塔的河内塔算法,为此我们给出了以下算法:

  • 将除底部圆盘以外的所有圆盘从源移动到中间塔
  • 将底部磁盘从源移动到目标
  • 将除底部圆盘以外的所有圆盘从中间凳移动到目标塔

该算法的实际代码(模型属于具有塔和盘的 Model 类,使用移动方法将盘从一个塔移动到另一个)产生:

def move_disks(n, source, intermediate, destination):

    """Move n disks from source to destination
    @param int n:
    @param int source:
    @param int intermediate:

    @param int destination:
    @rtype: None
    """
    if n > 1:
        move_disks(n - 1, source, destination, intermediate)
        move_disks(1, source, intermediate, destination)
        move_disks(n - 1, intermediate, source, destination)
    else: 
        model.move(source, destination)

现在对于四个凳子,我得到以下信息:

  • 使用所有四个塔将 n-i 圆盘移动到中间凳子上
  • 将 i 磁盘从原始塔移动到目标塔,仅使用三个可用塔
  • 将 ni 个最小的磁盘从中间塔移动到目标塔

手动玩磁盘和塔我得到 ni = 2 如果 n>=3 和 i = 1 如果 n = 2。 由于有 4 个可能的来源和目的地,在我自己的函数中,我有 5 个参数而不是 4 个:

def move_disks(n, source, intermediate, intermediate2, destination):

    """Move n disks from source to destination
    @param int n:
    @param int source:
    @param int intermediate:
    @param int intermediate2:
    @param int destination:
    @rtype: None
    """
    if n > 1:
        move_disks(n - i, source, intermediate 2 destination, intermediate)
        move_disks(1, source, intermediate, intermediate2, destination)
        move_disks(n - i, intermediate, intermediate2, source, destination)
    else:
        print("{} -> {}".format(source,destination)) # used to explicitly follow output in the console
        #model.move(source, destination) --> to be implemented when the function returns the right output

当我为 n=3 运行它时,我得到:

1 -> 3
1 -> 2
3 -> 2
1 -> 4
2 -> 3
2 -> 4
3 -> 4

这给出了与三个塔的解决方案相同的移动数。 四次大便的最佳解决方案应该是:

1 -> 3
1 -> 2
1 -> 4
2 -> 4
3 -> 4

问题肯定来自我对算法的理解,所以我尝试在干可擦除板上跟踪函数调用几个小时,但无济于事。

关于我应该做什么或寻找什么来解决这个算法的任何提示或技巧? 老实说,我很失落,也有点气馁。

我发现您的代码有两个问题。

首先是您在使用变量i而不在函数中定义它。 它在您的环境中可能具有全局价值,但对于给定的n可能不合适。 您可能应该让您的函数弄清楚i应该是什么并将其分配为局部变量。

第二个问题是您总是使用相同的四塔函数递归,而您描述的算法在中间步骤中应该只使用三塔。 这可能意味着您应该保留原始功能(在第一个代码块中),并为四塔功能使用其他名称。

如果我们将第一个函数move_disks3move_disks4 ,第二个move_disks4 ,则可以使其工作:

def move_disks3(n, source, intermediate, destination):
    """Move n disks from source to destination
    @param int n:
    @param int source:
    @param int intermediate:
    @param int destination:
    @rtype: None
    """
    if n > 1:
        move_disks3(n - 1, source, destination, intermediate)
        move_disks3(1, source, intermediate, destination)
        move_disks3(n - 1, intermediate, source, destination)
    else:
        print("{} -> {}".format(source,destination))

def move_disks4(n, source, intermediate, intermediate2, destination):
    """Move n disks from source to destination
    @param int n:
    @param int source:
    @param int intermediate:
    @param int intermediate2:
    @param int destination:
    @rtype: None
    """
    if n > 1:
        if n > 2: # I'm not sure this picks the optimal i in all cases, but it does for n=3
            i = 2
        else:
            i = 1
        move_disks4(n - i, source, intermediate2, destination, intermediate)
        move_disks3(i, source, intermediate2, destination)
        move_disks4(n - i, intermediate, intermediate2, source, destination)
    else:
        print("{} -> {}".format(source,destination))

我不确定我是否了解您关于最佳i值的声明,因此如果我在此处遇到问题,可能需要进行一些更改。 但是这段代码确实有效,并且确实给出了n = 3的期望结果(以及我测试的一些更高的n值的合理结果):

>>> move_disks4(3, 1, 2, 3, 4)
1 -> 2
1 -> 3
1 -> 4
3 -> 4
2 -> 4
def move4Poles(begin, end, temp1, temp2, disks):

    if disks == 1:
        print(begin, "to", end)
        return

    if disks == 2:
        move4Poles(begin, temp1, '_', '_', 1)
        move4Poles(begin, end, '_', '_', 1)
        move4Poles(temp1, end, '_', '_', 1)
        return

    if disks >= 3:
        move4Poles(begin, temp2, temp1, end, disks - 2)
        move4Poles(begin, end, temp1, '_', 2)
        move4Poles(temp2, end, temp1, begin, disks - 2)

move4Poles('A', 'D', 'B', 'C', 4)


A to B
A to C
B to C
A to B
A to D
B to D
C to B
C to D
B to D

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM