Python进阶之八皇后算法
1. 理解算法前提
1.1 理解遞歸
遞歸:recursion
簡單來說就是引用(或者調(diào)用)自身的意思。用遞歸實現(xiàn)的功能都可以用循環(huán)實現(xiàn),但是有些時候遞歸函數(shù)更易讀
# 通過循環(huán)實現(xiàn)冪函數(shù) def power(x, n):result = 1for i in range(n):result *= xreturn result# 通過遞歸實現(xiàn)冪函數(shù) def power(x, n):if n == 0:return 1else:# 注意此時調(diào)用power函數(shù)時的輸入:x, n-1# 如果是輸入: x, n 該函數(shù)將會陷入無限循環(huán), 直到運行崩潰return x * power(x, n-1)遞歸函數(shù)一定要以一個最小可能性問題結(jié)束,上述代碼中的最小可能性問題就是:n == 0
1.2 Python生成器
關(guān)鍵字:yield
任何包含yield語句的函數(shù)稱為生成器
生成器的行為和普通函數(shù)有很大的區(qū)別,它不像return那樣返回值,而是每次產(chǎn)生多個值。每次產(chǎn)生一個值(使用yield語句),函數(shù)就會被凍結(jié):即函數(shù)停在那點等待被重新喚醒。函數(shù)被重新喚醒后就從停止的那點開始執(zhí)行。
# 定義一個遞歸生成器 # 問題描述:按從左到右的順序取出序列中的每個元素,不論該序列內(nèi)部嵌套了多少層序列 # 此處忽略輸入為字符串的序列,我們測試的時候用列表 def flatten(nested):try:for sublist in nested:for element in flatten(sublist):yield elementexcept:yield nested# 調(diào)用該生成器 list(flatten([[[1],2],3,4,[5,[6,7]],8]))# 測試一下返回的到底是啥 g = flatten([[[1],2],3,4,[5,[6,7]],8]) print(g) while(True):try:print(next(g))except:break通過上述演示,我們可以看到生成器調(diào)用結(jié)束后返回了一個生成器對象,通過next函數(shù)可以逐個獲取生成器內(nèi)的每個返回值
如果上述遞歸生成器改成普通函數(shù),則需要一個額外的序列去存儲每次生成的element
2. 八皇后算法
2.1 八皇后問題描述
在8×8格的國際象棋上擺放8個皇后,使其不能互相攻擊,即任意兩個皇后都不能處于同一行、同一列或同一斜線上,問有多少種擺法
2.2 算法核心
2.2.1 檢測沖突
def conflict(state, nextX):'''檢測沖突, 邏輯如下state = (y1, y2, y3, ...)第一個皇后的位置: (0,y1)第二個皇后的位置: (1,y2)第三個皇后的位置: (2,y3)依此類推nextX 是下一個皇后的位置的x坐標, 從0開始'''# nextY 是下一個皇后的位置的y坐標, 從0開始, 于是: nextY = len(state)nextY = len(state)# 循環(huán)已知的皇后for i in range(nextY):# state[i] 是前面的皇后的位置的x坐標, i=0表示第一個皇后, i=1表示第二個皇后, 依次類推# 下一個皇后和前面任意一個皇后的位置的x坐標不能相同(同列), x坐標距離和y坐標距離不能相等(同斜線)if abs(nextX - state[i]) in (0, nextY - i):return Truereturn False2.2.2 基于Python生成器求解
def queens(num=8, state=()):# 從第一列判斷到第num-1列for pos in range(num):# 不沖突if not conflict(state, pos):# 已經(jīng)是最后一個皇后了if len(state) == num-1:# 返回此皇后的位置yield (pos,)else:# 遞歸獲取下一個皇后的位置, 輸入為:下一行列數(shù), 前面皇后的位置信息for result in queens(num, state + (pos,)):# 返回此皇后的位置 + 后面幾個皇后的位置, 因為是遞歸, 所以是此皇后的放前面yield (pos,) + result2.2.3 輸出結(jié)果并圖形化輸出擺法
def prettyprint(solution):def line(pos, length=len(solution)):print((' - ' * pos) + ' x ' + (' - ' * (length - pos - 1)))print(solution)for pos in solution:line(pos)# 輸出擺法 print(len(list(queens(4))))# 優(yōu)化輸出結(jié)果 for solution in queens(4):prettyprint(solution)Congratulations
恭喜你學習到了第一個用Python實現(xiàn)的經(jīng)典回溯算法——八皇后問題,更多進階內(nèi)容請繼續(xù)關(guān)注,感興趣記得訂閱哦!!!
總結(jié)
以上是生活随笔為你收集整理的Python进阶之八皇后算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10大黑客专用的 Linux 操作系统,
- 下一篇: websocket python爬虫_p