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