Python case: eight queens problem

Problem Description

There is an 8x8 chessboard with 8 chess pieces in it, and the row, column, and diagonal of each chess piece cannot have another chess piece. As follows, the first picture is a way to meet the conditions, and the second picture does not meet the conditions.
The Eight Queens problem is to expect to find all the conditions that meet the conditions.

Insert picture description here
Abstract the pendulum as a data structure

Obviously, the way to meet the conditions must be one pawn in each row. We can define a list, the index of the list represents the row number (starting from 0), and the value represents the column position (starting from 0).

For example, you can use the list [0,1,2,3,4,5,6,7] to represent the following situations:

O * * * * * * *
* O * * * * * *
* * O * * * * *
* * * O * * * *
* * * * O * * *
* * * * * O * *
* * * * * * O *
* * * * * * * O

When we need to output, we only need to restore the structure:

def print_queens(result):
    print('='*10)
    for i in result:
        print("* "*i,end="")
        if(i>=0):
            print("O ",end="")
        print("* "*(len(result) - i - 1))

How to judge whether a chess piece meets the requirements

Our idea is to place the chess pieces row by row from top to bottom, and check whether they meet the requirements after not placing a piece.

Then there are three types of non-conformities:

  1. There is already a piece directly above the piece;
  2. There is already a piece on the upper left diagonal of the piece;
  3. There is already a piece on the upper right diagonal of the piece;
O * * * * * * *
* * O * * * * *
* * * C * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *

The above situation can be represented by [0,2,-1,-1,-1,-1,-1,-1], where -1 means that the line has not been investigated yet, and the behavior we want to examine is the second line ( Start from 0).

We record the index of the row to be investigated as cur_index, and the value to be investigated is value. The three cases can be converted into the judgment of the list:

  1. There is already a piece right above the piece;
    the value already exists in the list, for example [0,2,2,-1,-1,-1,-1,-1]
  2. There is already a piece on the upper left diagonal of the piece; the
    index was previously pushed n places, and there is value-n = cur_index-n, for example [0,2,3,-1,-1,-1,-1,-1]
  3. There is already a piece on the upper right diagonal of the piece; the
    index was previously pushed by n places, and there is value-n = cur_index + n, for example [0,2,1,-1,-1,-1,-1,-1]
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
res = []

def check(row, column):
    # 逐行向上考察
    for (index, value) in enumerate(result[:row][::-1]):
        # 这三种分别表示在正上方,右上对角线,左上对角线存在棋子
        if value in [column, column + index + 1, column - index - 1]:
            return False
    result[row] = column
    return True

Multi-level for loop nesting to investigate all situations

This kind of code is best understood, but it is estimated to be crazy when written, and it cannot be extended to the problem of n queens.

def enum_queens_iter():
    length = len(result)
    for r0 in range(length):
        if check(0,r0):
            result[0] = r0
            for r1 in range(length):
                if check(1,r1):
                    result[1] = r1
                    for r2 in range(length):
                        if check(2,r2):
                            result[2] = r2
                            for r3 in range(length):
                                if check(3,r3):
                                    result[3] = r3
                                    for r4 in range(length):
                                        if check(4,r4):
                                            result[4] = r4
                                            for r5 in range(length):
                                                if check(5,r5):
                                                    result[5] = r5
                                                    for r6 in range(length):
                                                        if check(6,r6):
                                                            result[6] = r6
                                                            for r7 in range(length):
                                                                if check(7,r7):
                                                                    result[7] = r7
                                                                    print_queens(result)

Convert to recursive form

From the above code, we can see that there are a lot of repeated codes, and there is a structural relationship between the repeated codes. This kind of code can generally be converted into a recursive form.

In the following code, we only inspect the first line of the part to be inspected each time, and then inspect the remaining part when the requirements are met.

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
result = [-1] * 8
def enum_queens(row_index):
    length = len(result)

    # 考察当前部分的第一行
    for i in range(length):
        if(check(row_index,i)):
            if row_index == length - 1:
                global total_num
                total_num+=1
                print_queens(result)
            # 考察剩余的部分
            enum_queens(row_index+1)

if __name__ == "__main__":
    enum_queens(0)

Guess you like

Origin blog.csdn.net/sinat_38682860/article/details/108711766