1.回溯法
回溯法,又被稱為「試探法」。解決問題時,每進行一步,都是抱著試試
或者這麼走下去肯定達不到目標,立刻做回退操作重新選擇。這種走不通
就回退再走的方法就是回溯法。
問題: 列舉集合 中所有子集的問題中
使用回溯法。從集合的開頭元素開始,對每個元素都有兩直到集合最後乙個元素。
其中的每個操作都可以看作是一次嘗試,每次嘗試都可以得出乙個結果。將得到的
結果綜合起來,就是集合的所有子集。
回溯法從問題本身出發,尋找可能實現的所有情況。和窮舉法的思想相近,
不同在於窮舉而回溯法在列舉過程如果發現當前情況根本不可能存在,就
停止後續的所有工作,返回上一步進行新的嘗試。
遞迴是從問題的結果出發,例如求 n!,要想知道 n!的結果,就需要知道
n*(n-1)! 的結果,而要想知道 (n-1)! 結果,就需要提前知道 (n-1)*(n-2)!。
這樣不斷地向自己提問,不斷地呼叫自己的思想就是遞迴。
回溯和遞迴唯一的聯絡就是,回溯法可以用遞迴思想實現。
回溯法的求解過程實質上是先序遍歷「狀態樹」的過程。樹中每乙個葉子結點,都有可能是問題的答案。
2.八皇后問題
八皇后問題是以西洋棋為背景的問題:有八個皇后(可以當成八個棋子),如何在 8*8 的棋盤中放置八個皇后,使得任意兩個皇后都不在同一條橫線、縱線或者斜線上。
演算法思路:
從棋盤的第一行開始,從第乙個位置開始,依次判斷當前位置是否能夠放置皇后,
判斷的依據為:同該行之前的所有行中皇后的所在位置進行比較,如果在同一列,
或者在同一條斜線上(斜線有兩條,為正方形的兩個對角線),都不符合要求,
繼續檢驗後序的位置。
如果該行所有位置都不符合要求,則回溯到前一行,改變皇后的位置,繼續試探。
如果試探到最後一行,所有皇后擺放完畢,則直接列印出 8*8 的棋盤。最後一定
要記得將棋盤恢復原樣,避免影響下一次擺放。
實現**:
def conflict(state, nextcolumn):
"""state: (7, 4, 6, 0, 2) 標記已經排好的每個皇后的位置,(0,7), (1, 4), (2,6),(3,0),(4,2)
nextcolumn: 2 下一行八皇后準備要放置的列索引位置
利用回溯法判斷是否可以在第6行的第3列放置皇后, 如果可以,返回true, 如果不可以,返回false;
"""nextrow = rows = len(state) # 5
for row in range(rows): # row = 0 1 2 3 4
column = state[row]
if abs(column - nextcolumn) in (0, nextrow - row):
"""i=0:
state[0]=7, nextcolumn=2
如果差值等於0,兩個皇后在同一列, 則代表衝突, 返回true;
如果列的差值等與行的差, 兩個皇后在對角線上, 則代表衝突, 返回true;
"""return true
return false
# nums = 8 pos=()
def queens(num, state=()):
"""採用生成器的方式來產生每乙個皇后的位置,並用遞迴來實現下乙個皇后的位置。
num: 皇后的數量
state: 標記已經排好的每個皇后的位置
"""for pos in range(num): # 八皇后的數量n=0, 1, 2, 3, 4, 5, 6 , 7 你要在哪一列放置皇后
# 如果不衝突,則遞迴構造棋盤。
if not conflict(state, pos): # 回溯法的體現
# 如果棋盤狀態state已經等於num-1,即到達倒數第二行,而這時最後一行皇后又沒衝突,直接yield,打出其位置(pos, )
if len(state) == num - 1: # state=()
yield (pos,)
else: # (0, )
for result in queens(num, state + (pos,)):
"""pos = 0
(0, ) (0, 2), (0, 2, 4), ()
1). pos=0,第一行放在第一列,這時不會衝突,但是不會進入if,因為還沒到達倒數第二行, (0)
2). 進入else後,再呼叫queens(num, state+(pos,),這時進入第二行,再次遞迴展開則是queens(num,state+(pos, )+(pos, ) )
2). 進入else後,再呼叫queens(num, state+(pos,),這時進入第三行,再次遞迴展開則是queens(num,state+(pos, )+(pos, ) +(pos, ) )
3). 到達最後一行時返回(pos, ),再返回倒數第二行,再返回倒數第三行,最後到達最開始那層(pos, )+result, pos為第一行皇后所在列,
"""yield (pos,) + result
def prettyprint(solution): # (6, 1, 5, 2, 0, 3, 7, 4)
"""友好展示: 為了直觀表現棋盤,用x表示每個皇后的位置
:param solution:
:return:
"""def line(pos, length=len(solution)): # pos為6,即繪製在第7列 . . . . . . x .
return '. ' * (pos) + 'x ' + '. ' * (length - pos - 1)
for pos in solution:
print(line(pos))
if __name__ == '__main__':
solutions = queens(8)
for index, solution in enumerate(solutions):
print("第%d種解決方案:" % (index + 1), solution)
prettyprint(solution)
print('*' * 100)
八皇后演算法
imports system.math public class eightqueen dim topnum as int16 7 dim printb as boolean dim j2 as int16 0 dim eightqueenplace2 topnum 2 topnum 2 topnu...
回溯演算法 八皇后
總時間限制 1000ms 記憶體限制 65536kb 描述 會下西洋棋的人都很清楚 皇后可以在橫 豎 斜線上不限步數地吃掉其他棋子。如何將8個皇后放在棋盤上 有8 8個方格 使它們誰也不能被吃掉!這就是著名的八皇后問題。對於某個滿足要求的8皇后的擺放方法,定義乙個皇后串a與之對應,即a b 1b2....
回溯演算法 八皇后
今天學習了下回溯演算法,順便看了下經典案例 八皇后問題。該問題是國際西洋棋棋手馬克斯 貝瑟爾於1848年提出 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。回溯演算法的搜尋邏輯是深度優先,即,從一條路往前走,能進則進,不能進則...