问题:
在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上。问共有多少种不同的方法,并且指出各种不同的放法。
思路:
使用回溯法依次假设皇后的位置,当第一个皇后确定后,寻找下一行的皇后位置,当满足左上、右上和正上方向无皇后,即矩阵中对应位置都为0,则可以确定皇后位置,依次判断下一行的皇后位置。当到达第8行时,说明八个皇后安置完毕。
回溯法实现:
#八皇后问题
board = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]
]
#total记录多少种方法
total = 0
#判断(x,y)能否放皇后
def can_place(x, y):
# 判断(x,y)坐标能否放皇后
# 1. 判断x行是否有皇后
for i in range(0, y):
if board[x][i] == 1:
return False
# 2. 判断y列是否有皇后
for i in range(0, x):
if board[i][y] == 1:
return False
# 3. 判断"/"方向是否有皇后
for i in range(0, x):
if x + y - i <= 7 and board[i][x + y - i] == 1:
return False
# 4. 判断"\"方向是否有皇后
for index, i in enumerate(range(x - 1, -1, -1)):
s_y = y - (index + 1)
if s_y >= 0:
if board[i][s_y] == 1:
return False
return True
#打印
def print_board():
for i in range(8):
for j in range(8):
if board[i][j] == 0:
print("□ ", end=" ")
else:
print("■ ", end=" ")
print()
#回溯法查找适合的放法
def put_queen(step):
if step == 8:
print_board()
global total
total += 1
print("----------------")
else:
for i in range(8):
# 判断该位置是否能放当前皇后
if can_place(step, i):
# 1. 设置现场
board[step][i] = 1
# 2. 开始递归
put_queen(step + 1)
# 3. 恢复现场
board[step][i] = 0
if __name__ == "__main__":
put_queen(0)
print("总共有{}种方法".format(total))