Solving the n-queen puzzle

和自甴很熟 提交于 2019-12-04 11:18:43

The backtracking algorithm to the N-Queens problem is a factorial algorithm in the worst case. So for N=8, 8! number of solutions are checked in the worst case, N=9 makes it 9!, etc. As can be seen, the number of possible solutions grows very large, very fast. If you don't believe me, just go to a calculator and start multiplying consecutive numbers, starting at 1. Let me know how fast the calculator runs out of memory.

Fortunately, not every possible solution must be checked. Unfortunately, the number of correct solutions still follows a roughly factorial growth pattern. Thus the running time of the algorithm grows at a factorial pace.

Since you need to find all correct solutions, there's really not much that can be done about speeding up the program. You've already done a good job in pruning impossible branches from the search tree. I don't think there's anything else that will have a major effect. It's simply a slow algorithm.

The number of solutions can be estimated using Donald Knuth's randomised estimation method.

Starting from no queens placed the number of allowed positions for the next row is n. Randomly pick one of the positions and calculate the number of allowed positions (p) for the next row and multiple this by n and store it as the total number of solutions (total = n * p) , then randomly choose one of the allowed positions.

For this row calculate the number of allowed positions (p) for the next row and mutiple the total number of solutions by this (total *= p). Repeat this until either the board cannot be solved, in which case the number of solutions equals zero, or until the board is solved.

Repeat this many times and calculate the average number of solutions (including any zeros). This should give you a quick and pretty accurate approximation of the number of solutions with the approximation improving the more runs you do.

I hope this makes sense ;)

I would suggest you peek at the test_generators.py from the Python source for an alternative implementation of the N-Queens problem.

Python 2.6.5 (release26-maint, Sep 12 2010, 21:32:47) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from test import test_generators as tg
>>> n= tg.Queens(15)
>>> s= n.solve()
>>> next(s)
[0, 2, 4, 1, 9, 11, 13, 3, 12, 8, 5, 14, 6, 10, 7]
>>> next(s)
[0, 2, 4, 6, 8, 13, 11, 1, 14, 7, 5, 3, 9, 12, 10]

Just saw this question. I'd like to contribute 2 solutions.

  1. This one returns all distinct solutions

  2. This one returns the first valid solution found

Feedback is appreciated. Cheers

Below is my PYTHON implementation. You might want to use PYPY for more speed.

Its speed is helped by using an O(1) time method to check whether the next queen is attacked by those already placed on the board.

Assuming the program is "nqueen.py", an example to run it is "python nqueen.py 6", where 6 is the size of a 6x6 board.

#!/bin/python
#
# TH @stackoverflow, 2016-01-20, "N Queens" with an O(1) time method to check whether the next queen is attacked
#
import sys


board_size = int(sys.argv[1])
Attacked_H  = { i:0 for i in range(0, board_size) }
Attacked_DU = { i:0 for i in range(0, board_size*2) }
Attacked_DD = { i:0 for i in range(-board_size, board_size) }


def nqueen(B, N, row, col):
    if(row >= N):
        return 1
    if(col >= N):
        print "board:\n" + str.join("\n", ["_|"*q + "Q|" + "_|"*(board_size - q - 1) for q in B])
        return 0
    B[col] = row
    if(0==(Attacked_H[row] + Attacked_DU[row+col] + Attacked_DD[row-col])):
        [Attacked_H[row], Attacked_DU[row+col], Attacked_DD[row-col]] = [ 1,1,1 ]
        nqueen(B, N, 0, col + 1)
        [Attacked_H[row], Attacked_DU[row+col], Attacked_DD[row-col]] = [ 0,0,0 ]
    nqueen(B, N, row + 1, col)


nqueen(list(range(0, board_size)), board_size, 0, 0)

We can solve n-queens with genetic algorithms too. This is described here https://youtu.be/l6qll5OldHQ, in one of the lectures of the edX course ColumbiaX: CSMM.101x Artificial Intelligence (AI).

The objective function tries to optimize number of non-attacking pairs of queens. The animation below shows an example solution in R with n=20. Further details on how to solve n-queens with genetic algorithms can be found here: https://sandipanweb.wordpress.com/2017/03/09/solving-the-n-queen-puzzle-with-genetic-algorithm-in-r/?frame-nonce=76cf9b156a.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!