用于Python中四个塔的河内塔递归算法

时间:2017-02-12 00:12:23

标签: python algorithm recursion

我在为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个磁盘从原始塔移动到目标塔
  • 将n-i个最小的磁盘从中间塔移动到目标塔

手动玩磁盘和磁盘如果n> = 3,我得到n-i = 2,如果n = 2,则i = 1。由于有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

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

我还应该做些什么或者想要解决这个算法的任何提示或技巧?我老老实实地迷失了,有点气馁。

1 个答案:

答案 0 :(得分:0)

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

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

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

如果我们为您的第一个函数move_disks3和第二个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
相关问题