Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么偶数n比奇数n花费更长的时间?_Python_Backtracking_N Queens - Fatal编程技术网

Python 为什么偶数n比奇数n花费更长的时间?

Python 为什么偶数n比奇数n花费更长的时间?,python,backtracking,n-queens,Python,Backtracking,N Queens,我这里有一些代码,它使用python中的回溯解决了n queens问题。当我运行它时,赔率所用的时间总是比平均数少很多。当n达到20+左右时,这一点尤为明显。有人知道这是为什么吗 import time global N N = int(input("Enter N: ")) def display_solution(board): print('\n'.join(['\t'.join([str(cell) for cell in row]) for row in boar

我这里有一些代码,它使用python中的回溯解决了n queens问题。当我运行它时,赔率所用的时间总是比平均数少很多。当n达到20+左右时,这一点尤为明显。有人知道这是为什么吗

import time
global N
N = int(input("Enter N: "))


def display_solution(board):
    print('\n'.join(['\t'.join([str(cell) for cell in row]) for row in 
    board]))


def safe(board, row, col):
    for i in range(col):
        if board[row][i] == 1:
            return False
    for i, j in zip(range(row, -1, -1), range(col, -1, -1)):
        if board[i][j] == 1:
            return False
    for i, j in zip(range(row, N, 1), range(col, -1, -1)):
        if board[i][j] == 1:
            return False
    return True


def solve_help(board, col):
    if col >= N:
        return True

    for i in range(N):
        if safe(board, i, col):
            board[i][col] = 1
            if solve_help(board, col + 1) is True:
                return True
            board[i][col] = 0
    return False


def solve():
    board = [[0 for x in range(N)] for y in range(N)]
    if solve_help(board, 0) is False:
        print("Solution does not exist")
        return False
    display_solution(board)
    return True


start = time.clock()
solve()
end = time.clock()
print(N, "\t", end-start)

我想这一定是因为对角线的赔率不同于平均数。我也不确定这是否是这个问题的所有回溯算法的问题,或者只是这个特定代码的问题。不管是哪种方式,都要感谢您的帮助。

当第一列中的某一列出现回溯并且必须尝试下一行时,该算法需要花费相当多的时间。将奇数N块电路板与N-1块电路板进行比较表明,通常偶数电路板的解决方案需要进行更多的回溯/尝试下一步处理。例如,N=19的解决方案的左上角如下所示:

1 0 0 0 0
0 0 0 1 0
0 1 0 0 0
0 0 0 0 1*
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
0 0 0 1 0
0 1 0 0 0
0 0 0 0 0-
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1*
前五列中的这5个皇后很快就被找到了,因为它们是第一个不与之前的皇后碰撞的皇后。显然,其他的皇后可以被安置,而不必重新考虑前五个皇后

对于N=18,解决方案的同一角如下所示:

1 0 0 0 0
0 0 0 1 0
0 1 0 0 0
0 0 0 0 1*
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
0 0 0 1 0
0 1 0 0 0
0 0 0 0 0-
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1*
注意标有负号的位置。这一次看起来很有希望(就像对19号董事会一样):它的调查需要相当长的时间才能得出结论,即其他皇后不能被正确放置。这种早期的失败是有代价的

因此,19板的解决方案比18板更快找到

请注意,27的解决方案比26的解决方案花费的时间稍多,尽管这并不重要:看起来时间复杂度为O(2n),因此要比较不同电路板尺寸的时间,最好在对数Y轴上进行:

“工作”表示执行功能
safe
的次数

对于偶数板,该算法是否总是花费相对较多的时间(与N+1板所需的时间相比)尚不清楚,但对于这几个板尺寸,它似乎与该算法自然形成的骑士跳跃有关,从左上角开始。请注意,对于5号和7号电路板,此模式的效果是完美的:下一个皇后可以坐在的第一个位置,而不会干扰先前定位的皇后,这始终是解决方案的一部分。而对于尺寸为4和6的电路板,甚至没有一个角落有皇后的解决方案,这是该算法的起点

选择 从程序员的角度来看这个问题,有一种补救方法可以消除差异(平均而言):以不同(甚至随机)的顺序选择列。事实证明,采用正常顺序是获得解决方案的效率较低的方法之一

换档选择器

本算法中的一个简单移位,在不考虑前两行的情况下,除非所有其他的失败,都已经显著地改变了统计:

solve\u help
中更改此选项:

for i in range(N):
致:

看看平均性能现在是如何提高的:除n=6外,log(work)/n的所有度量值都低于1。但同时:对于N的奇数值,偷看现在更为频繁

随机挑选 下面是这样一次随机运行的结果:

比原来的顺序好多了!当然,你会得到一个坏的统计现在,然后。。。因为它是随机的。但平均而言,它的表现(好得多)

非随机顺序的其他方式可以包括具有不同系数的
col
N//2
,如
i=(i+col*2+N//2)%N
,…等。但请参见下面的最后一句话

其他意见 我将应用以下优化:跟踪哪些行、前向“对角线”和后向“对角线”已经被占用。您可以为此使用列表或集合。请注意,如果两个单元格的坐标之和相等,则这两个单元格位于同一正向对角线上。后对角线上的单元格有一个共同点,即它们的坐标差相等。这样,您就不必每次都在这些行中扫描“1”

此外,
board
可能只是列编号的列表。不需要存储所有这些零。把它留作展示用

最后,有一些简单的方法可以在线性时间内得到一个解。看