Algorithm 解决N皇后问题。。。我们能走多远?

Algorithm 解决N皇后问题。。。我们能走多远?,algorithm,prolog,clpfd,n-queens,Algorithm,Prolog,Clpfd,N Queens,N皇后问题: 这个问题表明,给定一个大小为N×N的棋盘,找出不同的排列方式,其中N个皇后可以放置在棋盘上,而没有任何一个皇后相互威胁 我的问题是: 程序可以在合理时间内计算答案的最大N值是多少?或者,到目前为止,我们看到的最大的N是什么? 以下是我在CLPFD(Prolog)中的程序: 这个程序运行得很好,但是它所花费的时间随着N的增加而不断增加。 下面是一个执行示例: ?- queens(4,L). L = [2, 4, 1, 3] ; L = [3, 1, 4, 2] ; No 这意

N皇后问题:

这个问题表明,给定一个大小为N×N的棋盘,找出不同的排列方式,其中N个皇后可以放置在棋盘上,而没有任何一个皇后相互威胁

我的问题是:
程序可以在合理时间内计算答案的最大N值是多少?或者,到目前为止,我们看到的最大的N是什么?

以下是我在CLPFD(Prolog)中的程序:

这个程序运行得很好,但是它所花费的时间随着N的增加而不断增加。 下面是一个执行示例:

?- queens(4,L).

L = [2, 4, 1, 3] ;

L = [3, 1, 4, 2] ;

No
这意味着您将4个皇后放置在第1列的第2行、第2列的第4行、第3列的第1行和第4列的第3行。(在4乘4的棋盘中)

现在让我们看看这个程序是如何执行的(计算第一次排列所花费的时间):
对于N=4,5…..秒内计算10次
对于N=11-30,需要-1-3秒
对于N=40..50,仍在一分钟内计算
当N=60时,它将退出全局堆栈(搜索空间巨大)

这是一个过去的家庭作业问题。(最初的问题只是对N皇后进行编码)


我也有兴趣看到其他语言的替代实现(性能比我的实现更好),或者我的算法/程序是否有改进的余地一个由raymond hettinger在pycon提出的简短解决方案:


计算所有排列是不可伸缩的,尽管(
O(n!)

我拖出一个旧的Delphi程序,该程序计算任何给定板大小的解决方案数量,并进行了快速修改,使其在一次点击后停止,我在数据中看到一个奇怪的模式:

第一块用了1秒时间求解的电路板是n=20。但在62毫秒内解决了21个问题。(注意:这是基于现在,不是任何高精度系统。)22花了10秒,直到28秒才重复

我不知道优化有多好,因为这原本是一个高度优化的例程,从那时起,优化的规则非常不同。不过,我做了一件与大多数实现非常不同的事情——它没有板。相反,我正在跟踪哪些列和对角线受到攻击,并在每行添加一个皇后。这意味着每个测试单元有3个数组查找,并且根本没有乘法运算。(正如我所说,从那时起,规则就大不相同了。)


现在让我们来看看真正的疯狂:29分钟花了9秒。30分钟花了将近6分钟

此讨论将三个不同的计算问题合并在一起:(1)找到N皇后问题的解决方案,(2)列出某些固定N的所有解决方案,以及(3)计算某些固定N的所有解决方案。第一个问题在开始时对于一块板的大小(如N=8)来说看起来很棘手。然而,正如维基百科所指出的,在某些关键方面,当N很大时,这很容易。大棋盘上的皇后们没有那么多的交流。除了内存限制外,随着N的增加,启发式修复算法的工作越来越容易

列出每个解决方案是不同的事情。这可能可以通过一个好的动态编程代码来完成,该代码的大小足够大,以至于读取输出没有意义

这个问题最有趣的版本是计算答案。最新的技术状态总结在一个神话般的参考称为。计算得出N=26。我猜这也使用了动态规划,但与列出每个解决方案的情况不同,算法问题更为深入,并有进一步的发展空间

Loren Pechtel说:“现在让我们来看看真正的疯狂:29分钟花了9秒。 30分钟就快6分钟了!”

对于不同的电路板尺寸,回溯复杂度缺乏可预测性,这是我最感兴趣的部分。多年来,我一直在构建一个列表,列出了每个板的大小需要使用<强>第一个解决方案< /强>所需的算法步骤的列表。C++中使用简单而熟知的深度优先算法。 这里列出了N=49的电路板的所有“计数”。。。减去仍在施工的N=46和N=48:

(我在整数序列百科全书(OEIS)中把它列为A140450

该页面包含一个指向匹配的第一个解决方案列表的链接

(我的第一个解决方案列表是OEIS序列号A141843

我主要不是记录每个解决方案需要多少处理时间,而是记录在发现每个板的算法第一个解决方案之前需要多少失败的皇后放置。当然,皇后放置的速度取决于CPU性能,但如果在特定CPU和特定板大小上进行快速测试,则很容易计算出解决这些“找到的”解决方案需要多长时间

例如,在英特尔奔腾D3.4GHz CPU上,使用单个CPU线程-

  • 对于N=35,我的程序每秒“放置”2400万个皇后,只需6分钟就能找到第一个解决方案
  • 对于N=47,我的程序每秒“放置”2050万个皇后,耗时199天
我目前的2.8GHz i7-860每秒要处理2860万个皇后,试图找到N=48的第一个解决方案。到目前为止,它已经花了550多天(理论上,如果它从来没有被中断过的话)才成功地安置了1369331731000000个皇后(并且迅速攀升)

我的网站还没有显示任何C++代码,但我确实在这个网页上给出了一个链接,简单地说明了解决N=5板所需的15个算法步骤中的每一个。


这确实是一个美味的拼图

如bakore所述,如果您只需要少量解决方案,那么实际上是受约束的随机行走(生成和测试),因为这些解决方案可以快速生成。我在20或21岁的时候为一个班级做了这件事,并在日记中发表了解决方案
?- queens(4,L).

L = [2, 4, 1, 3] ;

L = [3, 1, 4, 2] ;

No
#!/usr/bin/env python
from itertools import permutations
n = 12
cols = range(n)
for vec in permutations(cols):
    if (n == len(set(vec[i] + i for i in cols))
          == len(set(vec[i] - i for i in cols))):
        print vec
?- time((n_queens(100, Qs), labeling([ff], Qs))). Qs = [1, 3, 5, 57, 59 | ...] . 2,984,158 inferences, 0.299 CPU in 0.299 seconds (100% CPU, 9964202 Lips)
import numpy as np

n = int(raw_input("Enter n: "))

rs = np.zeros(n,dtype=np.int64)
board=np.zeros((n,n),dtype=np.int64)

k=0

if n%6==2 :

    for i in range(2,n+1,2) :
        #print i,
        rs[k]=i-1
        k+=1

    rs[k]=3-1
    k+=1
    rs[k]=1-1
    k+=1

    for i in range(7,n+1,2) :
        rs[k]=i-1
        k+=1

    rs[k]=5-1

elif n%6==3 :

    rs[k]=4-1
    k+=1

    for i in range(6,n+1,2) :
        rs[k]=i-1
        k+=1

    rs[k]=2-1
    k+=1

    for i in range(5,n+1,2) :

        rs[k]=i-1
        k+=1

    rs[k]=1-1
    k+=1
    rs[k]=3-1

else :

    for i in range(2,n+1,2) :

        rs[k]=i-1
        k+=1

    for i in range(1,n+1,2) :

        rs[k]=i-1
        k+=1

for i in range(n) :
    board[rs[i]][i]=1

print "\n"

for i in range(n) :

    for j in range(n) :

        print board[i][j],

    print