使用Warnsdorff规则进行的Knight巡回给出了错误的输出,且输出的大小通常为奇数

时间:2019-08-11 17:31:04

标签: python python-3.x algorithm knights-tour

我写了一个代码来解决knight's tour problem,问题是有时输出错误。

尤其是在板子尺寸奇数不多的情况下:例如,从[0,1]位置开始并以5X5的板子给我:

[[0, 1], [2, 0], [4, 1], [3, 3], [1, 4], [0, 2], [1, 0], [3, 1], [4, 3], [2, 2], [0, 3], [2, 4], [1, 2], [0, 0], [2, 1], [4, 0], [3, 2], [1, 3], [3, 4], [4, 2], [3, 0], [1, 1], [2, 3], [2, 3], [4, 4]]

如您所见,存在重复的[2,3]。我检查了给定电路板尺寸后算法得到多少错误输出,我发现在奇数尺寸下,正确的输出仅占50%的时间,而偶数尺寸则在大约99%的时间。怎么可能呢?

def rule(start , size):
    moves = [start ,]
    plus = [(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]
    while 1 == 1 :
        d = 7
        for x in plus:
            s = list(plus)
            c = 0
            q = [ start[0]+x[0] , start[1]+x[1] ]
            if valid(q , size , moves):
                    if len(moves) == size ** 2 -1 :
                        moves.append(q)
                        return moves
                    s.remove((-x[0] , -x[1]))
                    for y in s :
                        p = [ q[0]+y[0] , q[1]+y[1] ]
                        if valid(p , size , moves):
                            c = c+1
                    if 0 < c <= d :
                        l = q
                        d = c
        start = l
        moves.append(start)

def valid(q , size , moves):
    if 0 <= q[0] < size  and 0 <= q[1] < size :
        if q not in moves:
            return True
    return False

1 个答案:

答案 0 :(得分:0)

当所选路径遇到“死角”时会发生这种情况。

在您提到的示例中,起始点为[0,1],大小为5x5,这是在选择正方形[2,3]时(第一次)发生的。届时,仅需再访问2个正方形。它们是[0,4]和[4,4]。但是这些广场都没有邻居。

因此,c对于这两个有效的q移动都保持为0。这意味着l的值将被设置-保留其先前的值,仍然是[2,3]。因此,当您执行start = l

时,就会添加此重复项

Warnsdorff的规则并不能绝对保证实现此次旅行。在算法执行过程中的几个点上,都有联系-动作具有相等的c值。在这种情况下,您采用的最后一个值为c。但这可能是您需要从这些联系中选择另一个来获得成功。

因此,您要么必须实施回溯算法,即可检测到此类“死胡同”,然后回溯到出现平局的位置,然后从那里找到另一条路径。

或者您应该做一些更复杂的事情,因为似乎存在从关系中选择“正确”行动的方法。请参阅Wikipedia,以获得对两篇描述成功打破平局方法的文章的引用。