Python中的八个皇后问题

时间:2011-02-27 13:38:22

标签: python

Python中的8个皇后问题。

嗨!我只是开始教Python,所以有人可以解释下面写的代码(在Internet上找到)吗?有些代码对我来说很复杂。请解释一下。谢谢。问题就在代码附近。

BOARD_SIZE = 8

def under_attack(col, queens): # (col, queens) What is their meaning? What do I need to write it this field? 
    left = right = col
    for r, c in reversed(queens): # What does reversed means in this loop? For what reson do we need r and c (their meaning is 0 by default?)?
        left, right = left-1, right+1
        if c in (left, col, right):
            return True
    return False

def solve(n):
    if n == 0: return [[]]
    smaller_solutions = solve(n-1) # For what reasons do we need to write smaller_solutions?
    return [solution+[(n,i+1)] # What is solution (is it a function or what?)? What is value of i? 
        for i in range(BOARD_SIZE)
            for solution in smaller_solutions
                if not under_attack(i+1, solution)]
for answer in solve(BOARD_SIZE): print answer

谢谢!

4 个答案:

答案 0 :(得分:8)

您的代码错误(剪切和粘贴错误?),但这是要点:

您需要一份可能的解决方案列表。每个解决方案都是皇后列表。每个皇后都是一个元组 - 一行(整数)和一列(整数)。例如,BOARD_SIZE=1的解决方案是[[(1,1)]] - 单个解决方案 - [(1,1)]包含单个女王 - (1,1)放置在第1行和第1列。

smaller_solutions有8 BOARD_SIZE=8n=1 - [[(1,1)],[(1,2)],[(1,3)], [(1,4)],[(1,5)],[(1,6)],[(1,7)],[(1,8)]] - 一个皇后放在每一列第一行。

你理解递归吗?如果没有,请立即谷歌。

基本上,你首先将0个皇后添加到0号棋盘 - 这有一个简单的解决方案 - 没有皇后。然后你会找到将一个女王放在电路板第一排的解决方案。然后你寻找能够在第二排添加第二个女王的解决方案 - 某个地方没有受到攻击。等等。

def solve(n):
    if n == 0: return [[]] # No RECURSION if n=0. 
    smaller_solutions = solve(n-1) # RECURSION!!!!!!!!!!!!!!
    solutions = []
    for solution in smaller_solutions:# I moved this around, so it makes more sense
        for column in range(1,BOARD_SIZE+1): # I changed this, so it makes more sense
            # try adding a new queen to row = n, column = column 
            if not under_attack(column , solution): 
                solutions.append(solution + [(n,column)])
    return solutions

这解释了一般策略,但不是under_attack

under_attack可以重写,以便更容易理解(对我,你和你的学生):

def under_attack(column, existing_queens):
    # ASSUMES that row = len(existing_queens) + 1
    row = len(existing_queens)+1
    for queen in existing_queens:
        r,c = queen
        if r == row: return True # Check row
        if c == column: return True # Check column
        if (column-c) == (row-r): return True # Check left diagonal
        if (column-c) == -(row-r): return True # Check right diagonal
    return False

我的方法有点慢,但并不多。

旧的under_attack基本相同,但它会加快速度。它以相反的顺序查看existing_queens(因为它知道现有皇后的行位置将继续倒计时),跟踪左右对角线。

答案 1 :(得分:2)

BOARD_SIZE = 8

def under_attack(col, queens): # You do not need to fill in these fields. This is a helper function for the solve function.
    left = right = col
    for r, c in reversed(queens): # Reversing queens causes them to be iterated over in reverse order.
        left, right = left-1, right+1
        if c in (left, col, right):
            return True
    return False

def solve(n):
    if n == 0: return [[]]
    smaller_solutions = solve(n-1) # It appears that in solving this board, it solves all boards smaller than it in a recursive manner.
    return [solution+[(n,i+1)] # This line appears to be in error. Have you run this code and verified that it runs correctly?
        for i in range(BOARD_SIZE)
            for solution in smaller_solutions
                if not under_attack(i+1, solution)]
for answer in solve(BOARD_SIZE): print answer

答案 2 :(得分:0)

这是我的解决方案。它更容易理解和直接:

def under_attack(row, column, existing_queens):
    if not len(existing_queens): return False
    for queen in existing_queens:
        if not len(queen):
            continue
        r,c = queen
        if r == row: return True # Check row
        if c == column: return True # Check column
        if (column-c) == (row-r): return True # Check left diagonal
        if (column-c) == -(row-r): return True # Check right diagonal
    return False

def iter_solve(n):
    solutions = None
    for row in range(1, n+1):
        # for each row, check all valid column
        solutions = check(solutions, row, n)
    return solutions

def check(solutions, row, n):
    new_solutions = []
    for column in range(1, n+1):
        if not solutions or not len(solutions):
            new_solutions.append([] + [(row, column)])
        else:
            for solution in solutions:
                if not under_attack(row, column, solution):
                    new_solutions.append(solution + [(row, column)])
    return new_solutions

答案 3 :(得分:0)

  

这是源程序,此代码的输出将在单独的文件名中生成为“queen.txt”

import json
import sys

BOARD_SIZE = 8

def under_attack(col, queens):
    x = y = col

    for r, c in reversed(queens):
        x , y = x - 1, y + 1 #check for the prev queen location 

        if c in (x , col, y):
            return True
    return False

def solve(n): # n is the number of queens to be placed
    if n == 0:
        return [[]]

    smaller_solutions = solve(n - 1)

    return [solution+[(n,i+1)]
        for i in xrange(BOARD_SIZE)
            for solution in smaller_solutions
                if not under_attack(i+1, solution)] #call the function 

former, sys.stdout = sys.stdout, open('queen.txt','w')

for answer in solve(BOARD_SIZE):
    print answer

results, sys.stdout = sys.stdout, former #former is used for ip & op
print json.dumps(answer) #dumps is used to write in json file
  

输出文件会像这样[(1,4),(2,2),(3,7),(4,3),(5,6),   (6,8),(7,5),(8,1)] [(1,5),(2,2),(3,4),(4,7),(5,3),( 6,   8),(7,6),(8,1)] [(1,3),(2,5),(3,2),(4,8),(5,6),(6,4) )   (7,7),(8,1)]。 。 。 。 [(1,4),(2,7),(3,5),(4,2),(5,6),(6,   1),(7,3),(8,8)] [(1,5),(2,7),(3,2),(4,6),(5,3),(6,1) )   (7,4),(8,8)]