java數據結構之n皇后問題

n皇后問題:

每一行只能有一個皇后,每一列也只能有一個皇后,這個可以用col[edg] 數組來表示某一列是否已經有皇后;

對角線 / 有如下性質: 對於這種方向上經過同一條線的方格,其橫(i) 縱(j)座標的和都相等 i+j, 一共有2*n-1條這種對角線;

對角線\有如下性質:對於這種方向上經過同一條對角線的方格, 其橫(i) 縱(j)座標有如下關係:i - j + n - 1都相等, 一共有2*n條這種對角線。

 

運行:

8皇后一共有92種解決方案:
=====================0===================
Q    *    *    *    *    *    *    *    
*    *    *    *    Q    *    *    *    
*    *    *    *    *    *    *    Q    
*    *    *    *    *    Q    *    *    
*    *    Q    *    *    *    *    *    
*    *    *    *    *    *    Q    *    
*    Q    *    *    *    *    *    *    
*    *    *    Q    *    *    *    *    
=====================1===================
Q    *    *    *    *    *    *    *    
*    *    *    *    *    Q    *    *    
*    *    *    *    *    *    *    Q    
*    *    Q    *    *    *    *    *    
*    *    *    *    *    *    Q    *    
*    *    *    Q    *    *    *    *    
*    Q    *    *    *    *    *    *    
*    *    *    *    Q    *    *    *    
=====================2===================

...

代碼:

package cn.agan.recursive;

import java.util.ArrayList;

/**
 * 回溯法解決八皇后問題:
 *
 */

public class EightQueens {
    public static void main(String[] args) {
        ChessBoard chessBoard = new ChessBoard(8);
        chessBoard.findSolution(0);
        chessBoard.printChess();
    }
}


class ChessBoard {
    private int edg; //棋盤的邊,一般棋盤都是正方形的
    private ArrayList<ChessPoint[]> s;
    private int[] rows;
    private boolean[] col;
    private boolean[] dial1;
    private boolean[] dial2;

    public ChessBoard(int edg) {
        this.edg = edg;
        s = new ArrayList<>();
        rows = new int[edg];            //一個解決方案中,下標表示每一個皇后的第幾行,值表示其列
        col = new boolean[edg];         // |
        dial1 = new boolean[2*edg - 1]; // /:對於這種方向上經過同一條線的方格,其橫(i) 縱(j)座標的和都相等 i+j
        dial2 = new boolean[2*edg - 1]; // \:對於這種方向上經過同一條對角線的方格, 其橫(i) 縱(j)座標有如下關係:i - j + n - 1
    }

    public void findSolution( int rowIndex) {
        if (rowIndex == edg) {
            //得到一種解決方案,保存下
            saveSolution(rows);
            return ;
        }
         for (int i = 0; i < edg; i++) {
             if (!col[i] && !dial1[i+rowIndex] && !dial2[i-rowIndex+edg-1]) {
                 rows[rowIndex] = i;
                 col[i] = true;
                 dial1[i+rowIndex] = true;
                 dial2[i-rowIndex+edg-1] = true;
                 findSolution(rowIndex+1);
                 col[i] = false;
                 dial1[i+rowIndex] = false;
                 dial2[i-rowIndex+edg-1] = false;
             }

        }
         return;
    }

    //保存一個成功的擺放
    public void saveSolution(int[] rows) {
        ChessPoint[] tmp = new ChessPoint[rows.length];
        for (int i = 0; i < rows.length; i++) {
            ChessPoint chessPoint = new ChessPoint(i, rows[i]);
            tmp[i] = chessPoint;
        }
        s.add(tmp);
    }

    //打印所有的解決方案
    public void printChess() {
        System.out.println("一共有"+s.size() +"種解決方案:");
        for (int k = 0; k < s.size(); k++) {
            System.out.println("====================="+k+"===================");
            ChessPoint[] ps = s.get(k);
            for (int i = 0;  i < edg; i++) {
                for (int j = 0; j < edg; j++) {
                    if (ps[i].i == i && ps[i].j == j) {
                        System.out.printf("Q\t");
                    } else {
                        System.out.printf("*\t");
                    }
                }
                System.out.println();
            }
        }

    }
}

class ChessPoint {
    int i;
    int j;

    public ChessPoint(int x, int y) {
        i = x;
        j = y;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章