递归算法来源 《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)。 但回溯了,说明之前的设置占用位置需要重置。