我们可以解决N皇后没有回溯吗?以及如何计算回溯解决方案的复杂性?

时间:2013-09-04 09:22:54

标签: python algorithm complexity-theory time-complexity backtracking

我尝试使用回溯来解决这个问题,并打印出所有可能的解决方案。

出现了两个问题:

1. 我可以使用其他技术实现n queen吗?

2. 是否可以让以下代码仅打印第一个解决方案然后终止?

我目前的代码使用回溯:

n = 8

x = [-1 for x in range(n)]

def safe(k,i):
    for j in xrange(k):
          if x[j] == i  or abs(x[j] - i) == abs(k - j) :
          return False
    return True


def nqueen(k):
    for i in xrange(n):
        if safe(k,i):
            x[k] = i 
        if k == n-1:
            print "SOLUTION", x
        else:
            nqueen(k+1)

nqueen(0)

注意:我对不依赖于特定编程语言的技术感兴趣。

2 个答案:

答案 0 :(得分:3)

根据Wikipedia,您可以使用启发式方法:

这种启发式解决了任何N≥4的N个皇后。它形成了水平位置(列)简单增加的皇后垂直位置(行)的数字列表。八个女王之谜的N是8。

  1. 如果N除以6的余数不是2或3那么列表就是所有偶数后跟所有奇数≤N
  2. 否则,写出偶数和奇数的单独列表(即2,4,6,8 - 1,3,5,7)
  3. 如果余数为2,则在奇数列表中交换1和3并将5移至末尾(即3,1,7,5)
  4. 如果余数为3,则将2移至偶数列表的末尾,将1,3移至奇数列表的末尾(即4,6,8,2 - 5,7,9,1,3)
  5. 将奇数列表附加到偶数列表,并将皇后从左到右放置在这些数字给出的行中(即a2,b4,c6,d8,e3,f1,g7,h5)
  6. 这种启发式方法是O(n),因为它只是在一些if语句之后打印结果。

    关于你的第二个问题:“是否可以在下面制作代码,只打印第一个解决方案然后终止?”

    您可以在打印后致电sys.exit(0)

    import sys
    n = 8
    
    x = [-1 for x in range(n)]
    
    def safe(k,i):
        for j in xrange(k):
              if x[j] == i  or abs(x[j] - i) == abs(k - j) :
              return False
        return True
    
    
    def nqueen(k):
        for i in xrange(n):
            if safe(k,i):
                x[k] = i 
                if k == n-1:
                    print "SOLUTION", x
                    sys.exit(0)
                else:
                    nqueen(k+1)
    
    nqueen(0)
    

    或者,您可以返回一个值,然后传播该值,如果它指示终止:

    n = 8
    
    x = [-1 for x in range(n)]
    
    def safe(k,i):
        for j in xrange(k):
              if x[j] == i  or abs(x[j] - i) == abs(k - j) :
              return False
        return True
    
    
    def nqueen(k):
        for i in xrange(n):
            if safe(k,i):
                x[k] = i 
                if k == n-1:
                    print "SOLUTION", x
                    return True # Found a solution, send this good news!
                else:
                    if nqueen(k+1): # Good news!
                        return True # Share the good news to parent!
        return False # We have searched every possible combinations, and I regret to tell you that I could not find any solution.
    
    nqueen(0)
    

    至于时间复杂度,因为它是一个完整的搜索,它是n^n。虽然由于修剪(使用safe(k,i),但在实践中它更快。

答案 1 :(得分:2)

在没有回溯的情况下解决N级皇后的问题还有另一个有趣的问题。是否有几乎完美的女王放置启发式,以便在回溯框架中,您几乎总能找到有效的配置?这相当于说启发式几乎总是告诉你将下一个女王放在棋盘上的正确方格。这种启发式方法比已知的封闭式解决方案更有趣,它为所有N值提供了有效的配置(显然N = 2和3除外)。

几乎完美的最小回溯启发式分析是一个已在文献中研究过的问题。最重要的参考文献是[Kalé 90] [San Segundo 2011]。将下一个女王置于回溯框架中的最佳启发式似乎如下:

  1. 选择限制最多的行以放置下一个女王(即可用较少的方格)
  2. 从(1)中的行中选择关闭最少对角线数最少限制策略)的行。
  3. 此处关闭对角线指的是取消所有可用的正方形