1. 程式人生 > >用回溯法解決八皇后問題(Java實現)

用回溯法解決八皇后問題(Java實現)

八皇后問題,是一個古老而著名的問題,是回溯演算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認為有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了40種不同的解,後來有人用圖論的方法解出92種結果

—-以上內容引自百度百科。

本程式的功能是列印八皇后的所有擺放方式,用回溯法解決,使用的語言是Java,主要函式在程式碼中都有註釋。

主要思想是:從第0行開始擺放皇后,第0行擺放完畢後,就擺放第1行,以此類推…當第7行擺放完畢,即棋盤上已經有了8個皇后,就打印出所有皇后的路徑。接下來,就從第8個皇后開始,逐一將擺放好的皇后撤回。每撤回一個,就試探該行的其它位置(因為我們要列印所有正確的擺法)。

程式如下:

從執行結果可以看出:八皇后共有92種擺法。

public class EightQueen{

    private static final int SIZE = 8;  //皇后的個數,此處設為8,表示8個皇后

    private static int count = 0;  //記錄擺放的方式數

    public static void main(String[] args) {

        LinkedList<Location> list = new LinkedList<Location>();

        eightQueen(list, 0
, 0); //從棋盤的第0行第0列開始 System.out.println("八皇后共有 " + count + "種擺放方式"); } /** * 定義位置的數列結構,用於表示皇后的擺放位置 */ static class Location { int x ; //對應棋盤的列 int y ; //對應棋盤的行 Location(int x, int y){ this.x = x; this.y = y; } @Override
public String toString() { return "(" + x + ", " + y + ")"; } } /** * 主要函式,用回溯法。 */ private static void eightQueen(LinkedList<Location> list, int x, int y) { if(list.size() == SIZE){ //當list元素個數為8時,表示8個皇后都擺放完畢,列印後即可退出函式。 printLocation(list); //列印皇后擺放方式 return ; } for(int i = x ; i < SIZE ; i++){ Location loc = new Location(i, y); if(isLegalLoc(list, loc)){ list.offer(loc); //將第y行的皇后擺放好 eightQueen(list, 0, y+1); //開始擺放y+1行的皇后,同樣從第0列開始擺放 list.pollLast(); //每次擺放完一個皇后後,都要將其撤回,再試探其它的擺法。 } } } /** * 判斷位置為loc的皇后是否合法 */ private static boolean isLegalLoc(LinkedList<Location> list, Location loc) { for(Location each : list){ if(loc.x == each.x || loc.y == each.y) //判斷是否在同一行或同一列 return false; else if (Math.abs(loc.x - each.x) == Math.abs(loc.y - each.y)) //判斷是否在同一對角線或反對角線上 return false; } return true; } /** * 列印皇后擺放方式 * @param list */ private static void printLocation(LinkedList<Location> list) { for(Location each : list){ System.out.print(each.toString() + "\t"); } System.out.println(); count ++; } }