递归算法来源 《Combinatorial generation》,是我见过的最优雅的八皇后解法了。书里对应的通用迭代回溯算法,实在没有转化成功。但在理解递归解法之后,还是把拼图完成了。

递归版;

a = [True for _ in range(0, 9)]   # begin a[1]
b = [True for _ in range(0, 18)]  # begin b[2]
c = [True for _ in range(0, 16)]  # -7 to 7
x = [0 for _ in range(0, 9)]
g = 0


def print_queen():
    for i in range(1, 9):
        for j in range(1, 9):
            if x[j] == i:
                print("Q  ", end="")
            else:
                print("*  ", end="")
        print("\n")
    print("------------  count:%d--------------", g)


def queen(col):
    global g
    # eight queue question
    for row in range(1, 9):
        if a[row] and b[row + col] and c[row - col]:
            x[col] = row
            a[row] = b[row + col] = c[row - col] = False
            if col < 8:
                queen(col + 1)
            else:
                g += 1
                print_queen()
            a[row] = b[row + col] = c[row - col] = True

if __name__ == "__main__":
    queen(1)

a: indicate if a row does not contain a queue
b: indicate if a diagonal does not contain a queue
c: indicate if a diagonal does not contain a queue (opposite direction from b)

放置好了一个皇后之后,它的攻击位置也就确定了。

a[row] 表示这一行不能再放。

b[row+col] 表示下一列放置时,现在位置的右上角不能放 ( 判断时, row -1 + col + 1 = row + col)

c[row-col] 表示下一列放置时,现在位置的右下角不能放(判断时, row + 1 - (col + 1)= row - col)

 

迭代版:


def queen_iter():
    global g
    col = 1
    while col > 0:
        for row in range(x[col] + 1, 9):
            if a[row] and b[row + col] and c[row - col]:
                x[col] = row
                a[row] = b[row + col] = c[row - col] = False
                if col == 8:
                    g += 1
                    print_queen()
                    a[row] = b[row + col] = c[row - col] = True
                else:
                    col += 1
                    break
        else:
            x[col] = 0
            col = col - 1
            a[x[col]] = b[x[col] + col] = c[x[col] - col] = True
            continue

 

要点:

1.  print_queen 之后,赋值是恢复。已经成功了之后,它的占用不再需要。

2.  for 循环之后的 else。表示需要回溯了(col = col -1)。 但回溯了,说明之前的设置占用位置需要重置。

 

jiamo post at 2021-04-18