經典算法之八皇後問題

那时候天总是很蓝 2024-04-16 22:00 14次浏览 0 条评论 taohigo.com

八皇後問題是一個古老而又著名的問題,是學習回溯算法的一個經典案例。今天我們就一起來探究一下吧!

時間退回到1848年,國際西洋棋棋手馬克斯·貝瑟爾提出瞭這樣的一個問題,

後面陸續有不同的學者提出自己的見解。大數學傢高斯認為一共有76種擺法,1854年在柏林的象棋雜志上不同的作者發表瞭共計40種不同的見解,後來還有人利用圖論的方法得出共有92種擺法。

而如今,通過我們的計算機以及編程語言我們可以輕松的解決這個問題。

最直接的也是最容易想到的一種解法便是暴力法,我們可以在8×8的格子中任選8個皇後,選定後看是否滿足任意兩個皇後都不處於同行同列同斜線的條件,若滿足則累計滿足條件的方案。學習過排列組合的我們發現64取8這個數字達到瞭40億,顯然是令人難以接受的。

但我們根據這個條件,我們可以人為地做出一些選擇,比如根據條件我們可知每行每列最多都隻能有一個皇後,這樣可以在一定程度上縮減問題的規模。在第一行的某一列選擇放置一個皇後,共有8種不同的選擇,而第二行隻能選擇剩下的7列,也就是7種選擇,剩下每一行的選擇都會遞減1,那麼總共可供選擇的方案有8的階乘種,已經是一種遠優於暴力解法的解法,但是這個階乘的時間復雜度恐怕也難以令人接受,還有更優的解法嗎?

那是自然的,這便是遞歸回溯的方法。

當我們選擇瞭第一個皇後的位置之後,與其處於同行同列同斜線的位置便都無法被選擇,第二個皇後隻能放在未被第一個皇後所輻射到的位置上,接著放置第三個皇後,同樣不能放在被前兩個皇後輻射到的位置上,若此時已經沒有未被輻射的位置能夠被選擇,也就意味著這種擺法是不可行的,我們需要回退到上一步,給第二個皇後重新選擇一個未被第一個皇後輻射的位置,再來看是否有第三個皇後可以擺放的位置,如還是沒有則再次回退至選擇第二個皇後的位置,若第二個皇後也沒有更多的選擇則回退到第一個皇後,重新進行位置的選擇。

整體的方法便如上所述,下面用直觀的代碼來實現這個算法,

def find_Queen(row):

if row>7:
global count
count+=1
print_queen()
return

for column in range(8):
if check(row,column):
Queen[row][column]=1
find_Queen(row+1)
Queen[row][column]=0