生活随笔
收集整理的這篇文章主要介紹了
回溯法求解N皇后问题(Java实现)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
回溯法: 也稱為試探法,它并不考慮問題規(guī)模的大小,而是從問題的最明顯的最小規(guī)模開始逐步求解出可能的答案,并以此慢慢地?cái)U(kuò)大問題規(guī)模,迭代地逼近最終問題的解。這種迭代類似于窮舉并且是試探性的,因?yàn)楫?dāng)目前的可能答案被測(cè)試出不可能可以獲得最終解時(shí),則撤銷當(dāng)前的這一步求解過程,回溯到上一步尋找其他求解路徑。
為了能夠撤銷當(dāng)前的求解過程,必須保存上一步以來的求解路徑,這一點(diǎn)相當(dāng)重要。
光說不做沒意思,用學(xué)過的算法題來運(yùn)用一下。
N 皇后問題: 在一個(gè) N * N 的國際象棋棋盤中,怎樣放置 N 個(gè)皇后才能使 N 個(gè)皇后之間不會(huì)互相有威脅而共同存在于棋局中,即在 N * N 個(gè)格子的棋盤中沒有任何兩個(gè)皇后是在同一行、同一列、同一斜線上。
求解思路: 最容易想到的方法就是有序地從第 1 列的第 1 行開始,嘗試放上一個(gè)皇后,然后再嘗試第 2 列的第幾行能夠放上一個(gè)皇后,如果第 2 列也放置成功,那么就繼續(xù)放置第 3 列,如果此時(shí)第?3 列沒有一行可以放置一個(gè)皇后,說明目前為止的嘗試是無效的(即不可能得到最終解),那么此時(shí)就應(yīng)該回溯到上一步(即第 2 步),將上一步(第 2 步)所放置的皇后的位置再重新取走放在另一個(gè)符合要求的地方…如此嘗試性地遍歷加上回溯,就可以慢慢地逼近最終解了。
需要解決的問題: 如何表示一個(gè) N * N 方格棋盤能夠更有效?怎樣測(cè)試當(dāng)前所走的試探路徑是否符合要求?這兩個(gè)問題都需要考慮到使用怎樣的數(shù)據(jù)結(jié)構(gòu),使用恰當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)有利于簡(jiǎn)化編程求解問題的難度。
為此,我們使用以下的數(shù)據(jù)結(jié)構(gòu):
int column[col] =?row ?表示第 col?列的第?row 行放置一個(gè)皇后
boolean rowExists[i] = true ?表示第 i 行有皇后
boolean a[i] = true ?表示右高左低 的第 i 條斜線有皇后(按?→? ↓ 順序 從1~ 2*N -1 ?依次編號(hào))
boolean b[i] = true ?表示左高右低 的第 i 條斜線有皇后(按?→? ↑ 順序 從1~ 2*N -1 ?依次編號(hào))
對(duì)應(yīng)這個(gè)數(shù)據(jù)結(jié)構(gòu)的算法實(shí)現(xiàn)如下:
? ? ? ? public ?class ?N_Queens?{ ????? ? ????? ????private ?int ?queensNum?=?4 ; ? ? ????? ????private ?int []?queens?=?new ?int [queensNum?+?1 ]; ? ? ????? ????private ?boolean []?rowExists?=?new ?boolean [queensNum?+?1 ]; ? ? ????? ????private ?boolean []?a?=?new ?boolean [queensNum?*?2 ]; ? ? ????? ????private ?boolean []?b?=?new ?boolean [queensNum?*?2 ]; ? ???? ? ????? ????private ?void ?init()?{ ? ????????for ?(int ?i?=?0 ;?i?<?queensNum?+?1 ;?i++)?{ ? ????????????rowExists[i]?=?false ; ? ????????} ? ???????? ? ????????for (int ?i?=?0 ;?i?<?queensNum?*?2 ;?i++)?{ ? ????????????a[i]?=?b[i]?=?false ; ? ????????} ? ????} ? ? ????? ????private ?boolean ?isExists(int ?row,?int ?col)?{ ? ????????return ?(rowExists[row]?||?a[row?+?col?-?1 ]?||?b[queensNum?+?col?-?row]); ? ????} ? ? ????? ????public ?void ?testing(int ?column)?{ ? ? ????????? ????????for ?(int ?row?=?1 ;?row?<?queensNum?+?1 ;?row++)?{ ? ????????????? ????????????if ?(!isExists(row,?column))?{ ? ????????????????? ????????????????queens[column]?=?row; ? ????????????????? ????????????????rowExists[row]?=?a[row?+?column?-?1 ]?=?b[queensNum?+?column?-?row]?=?true ; ? ???????????????? ? ????????????????? ????????????????if (column?==?queensNum)?{ ? ????????????????????for (int ?col?=?1 ;?col?<=?queensNum;?col++)?{ ? ????????????????????????System.out.print("(" +col?+?"," ?+?queens[col]?+?")??" ); ? ????????????????????} ? ????????????????????System.out.println(); ? ????????????????}else ?{ ? ????????????????????? ????????????????????testing(column?+?1 ); ? ????????????????} ? ????????????????? ????????????????rowExists[row]?=?a[row?+?column?-?1 ]?=?b[queensNum?+?column?-?row]?=?false ; ? ????????????} ? ????????} ? ????} ? ???? ? ????? ????public ?static ?void ?main(String[]?args)?{ ? ????????N_Queens?queen?=?new ?N_Queens(); ? ????????queen.init(); ? ????????? ????????queen.testing(1 ); ? ????} ? }? 當(dāng) N = 8 時(shí),求解結(jié)果如下(注:橫坐標(biāo)為 列數(shù), 縱坐標(biāo)為 行數(shù) ):
(1 ,1 )??(2 ,5 )??(3 ,8 )??(4 ,6 )??(5 ,3 )??(6 ,7 )??(7 ,2 )??(8 ,4 )?? ? (1 ,1 )??(2 ,6 )??(3 ,8 )??(4 ,3 )??(5 ,7 )??(6 ,4 )??(7 ,2 )??(8 ,5 )?? ? (1 ,1 )??(2 ,7 )??(3 ,4 )??(4 ,6 )??(5 ,8 )??(6 ,2 )??(7 ,5 )??(8 ,3 )?? ? ...?... ? ...?... ? (1 ,8 )??(2 ,2 )??(3 ,4 )??(4 ,1 )??(5 ,7 )??(6 ,5 )??(7 ,3 )??(8 ,6 )?? ? (1 ,8 )??(2 ,2 )??(3 ,5 )??(4 ,3 )??(5 ,1 )??(6 ,7 )??(7 ,4 )??(8 ,6 )?? ? (1 ,8 )??(2 ,3 )??(3 ,1 )??(4 ,6 )??(5 ,2 )??(6 ,5 )??(7 ,7 )??(8 ,4 )?? ? (1 ,8 )??(2 ,4 )??(3 ,1 )??(4 ,3 )??(5 ,6 )??(6 ,2 )??(7 ,7 )??(8 ,5 )??? 當(dāng) N = 4 時(shí),求解結(jié)果如下: (1 ,2 )??(2 ,4 )??(3 ,1 )??(4 ,3 )?? ? (1 ,3 )??(2 ,1 )??(3 ,4 )??(4 ,2 )?? 有時(shí)間的話將輸出的結(jié)果打印為直觀一點(diǎn)的符號(hào)形式或界面形式更好。 小結(jié): 1、根據(jù)問題選擇恰當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)非常重要,就像上面 a 、b 標(biāo)志數(shù)組來表示每一條斜線的編號(hào)順序以及方向都相當(dāng)重要。看書的時(shí)候也是費(fèi)了些時(shí)間來理解的,呼…另外,queens [col] = row?數(shù)組只是用了一維而不是二維來表示縱橫交錯(cuò)的方格棋盤上特定位置是否有皇后也是比較經(jīng)濟(jì)而有意思的。 2、正確運(yùn)用、組織所確定的數(shù)據(jù)結(jié)構(gòu)到算法的實(shí)現(xiàn)邏輯中也是很重要的,就像代碼中的 isExists(int row, int col) 方法內(nèi)的?(rowExists[row] || a[row + col - 1] || b[queensNum + col - row]) 就是很明確的理解了嘗試放置皇后的位置的 x ,y 坐標(biāo)與斜線之間的數(shù)值關(guān)系,才使得算法得以正確執(zhí)行 。當(dāng)然,對(duì)于斜線的編號(hào)、順序也是相當(dāng)重要的。 本文轉(zhuǎn)自 xxxx66yyyy 51CTO博客,原文鏈接:http://blog.51cto.com/haolloyin/353105,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者
總結(jié)
以上是生活随笔 為你收集整理的回溯法求解N皇后问题(Java实现) 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。