八皇后问题python_python求解八皇后问题
今天突然有個(gè)行外的朋友扔了一張圖給我,希望我能幫他用python做一下這個(gè)作業(yè)——八皇后問題。
八皇后問題是一種經(jīng)典的數(shù)學(xué)求解問題,規(guī)則是在8×8的國際象棋棋盤上,要求在每一行(或者每一列)放置一個(gè)皇后,且能做到在水平方向、豎直方向和斜方向都沒有沖突。
關(guān)于這個(gè)問題的編程實(shí)現(xiàn),首先我們將棋盤等價(jià)于一個(gè)8×8的矩陣(二維數(shù)組),矩陣中的點(diǎn)(x,y)指代棋盤第x行y列的位置。而沖突的自然語言定義是同行、同列或同對(duì)角線,那么這個(gè)邏輯換算到程序中,我們可以認(rèn)為兩點(diǎn)(x1,y1)和(x2,y2)至少滿足以下四個(gè)條件之一:
同行:x1 = x2
同列:y1 = y2
斜線正方向:x1 + y1 = x2 + y2
斜線反方向:x1 - y1 = x2 - y2
一開始看到這個(gè)問題的規(guī)則,我有些小瞧了它的難度,以為通過逐行排除過濾就可以推出可行解,因此稍微整理一下思路就草草開干了,最后毫無疑問地踩了不少坑。在這個(gè)問題上,逐行定點(diǎn)的方式是可行的,關(guān)鍵在于八皇后問題在這種求解方式下存在死解,即可能在中途某行進(jìn)行取點(diǎn)時(shí),發(fā)現(xiàn)該行上沒有一個(gè)點(diǎn)符合要求。因此,八皇后問題的程序求解歸根到底其實(shí)是一個(gè)回溯遍歷的問題。通過回溯,我重新調(diào)整了思路:
1、從第一行開始,按照沖突規(guī)則過濾出每行目前可選的位置點(diǎn)集合,取一點(diǎn);
2、如果遇到死解,即當(dāng)前行沒有符合要求的可選點(diǎn),則回退到上一行,重新取點(diǎn);
3、直到第八行取到了符合要求的安全位置,求解成功。
捋清了這個(gè)編程思路,利用python實(shí)現(xiàn)也就不難了。
import random
import math
# 棋盤初始化
# params
# -d: 矩陣的大小
def initial_chessboard(d):
chessboard = [[(x+1, y+1) for y in range(d)] for x in range(d)]
return chessboard
# 指定行過濾出可選位置并隨機(jī)選取一個(gè),作為本行queen的填入位置
# params
# -chessboard:棋盤矩陣
# -rowIndex: 指定矩陣的某一行的序號(hào)
# -placePicked:已被選的位置
# -exclusions: 回溯時(shí)的排除項(xiàng)列表
def filter_and_pick_place(chessboard, rowIndex, placePicked, exclusions):
# 取到該行
row = chessboard[rowIndex]
# 在后續(xù)過程中保存本行過濾完的可選位置
alternative = []
if len(placePicked) != 0:
# 遍歷本行的每一項(xiàng)
for column in row:
# 這個(gè)變量標(biāo)志了該位置是否可用,初始化的時(shí)候是False,可用
available = True
# 遍歷已被選的位置
for item in placePicked:
# 只要有一個(gè)出現(xiàn)同列或同對(duì)角線,或位于排除項(xiàng)列表中時(shí),將available標(biāo)記為不可用
if column[1] == item[1] or column[0]+column[1] == item[0]+item[1] or \
column[0]-column[1] == item[0]-item[1] or column in exclusions:
available = False
# 該位置可用,添加進(jìn)可用項(xiàng)數(shù)組里
if available:
alternative.append(column)
else:
alternative = row
if len(alternative) == 0:
# 死解,返回0,指示不成功
return 0
else:
# 活解,隨機(jī)挑選位置點(diǎn),返回1,指示成功
randomIndex = math.floor(len(alternative) * random.random())
pick = alternative[randomIndex]
placePicked.append(pick)
return 1
# 根據(jù)最終結(jié)果用圖表展示出來
# params
# -positions: 最終挑選的位置列表
def generate_figure(positions):
figureSring = ''
for row in range(8):
for col in range(8):
if (row+1, col+1) in positions:
figureSring += 'x '
else:
figureSring += '- '
figureSring += '\n'
return figureSring
if __name__ == '__main__':
chessboard = initial_chessboard(8)
placePicked = []
exclusions = [[] for i in range(8)]
row = 0
while row < 8:
success = filter_and_pick_place(chessboard, row, placePicked, exclusions[row])
if success == 1:
# 沒有遇到死解,繼續(xù)往下
row += 1
else:
# 遇到了死解,回退到上一行并且將死解的點(diǎn)存入排除項(xiàng)中,重新選點(diǎn)
row -= 1
exclusions[row].append(placePicked.pop())
# 由于是自上而下選點(diǎn)的方式,當(dāng)上一行的點(diǎn)重新選取時(shí),后一行的排除項(xiàng)已經(jīng)沒有意義了,清空
if row < 7:
exclusions[row+1] = []
# 打印出棋盤
print(generate_figure(placePicked))
最終結(jié)果如下:
$ python eight_queens.py
- - - x - - - -
- - - - - - - x
- - - - x - - -
- - x - - - - -
x - - - - - - -
- - - - - - x -
- x - - - - - -
- - - - - x - -
總結(jié)
以上是生活随笔為你收集整理的八皇后问题python_python求解八皇后问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云电脑真的能取代传统电脑吗云电脑会取代传
- 下一篇: python sanic orm_San