趣談八皇后問題

Money is not everything. There's MasterCard.
金錢不是萬能的, 有時還須要信用卡。

背景

大話西遊之月光寶盒這部電影已經刷了N遍了。每一次看都有每一次的感悟。若是時光能夠到倒流,我當初就不該該。。。 悔不當初,悔不當初。git


雖然世界上沒有後悔藥,可是算法界倒是有後悔藥的,呢就是---回溯算法。人生不能時光倒流,呢我讓個人算法時光倒流。github

 八皇后問題最先是由國際象棋棋手馬克斯·貝瑟爾於1848年提出的,如今都21世紀了,八皇后怎麼能知足我,我決定實現一個N皇后,我想要幾個皇后就要幾個皇后。
算法

全部源碼均已上傳至github:連接數組

N皇后

思考

家家有本難唸的經,一個皇后已經了不起了。這N皇后嘛,可得好好處理,不能讓她們打架。能夠先聲明一個大小爲N的一維數組,來存儲個人這N位皇后。而後分紅N個階段。bash

  • 第一個階段隨便選一個位置。
  • 第二個階段須要判斷一下個人橫排,豎排,左對角線,右對角線(只須要和第一階段和自己相比便可)有沒有皇后。若是沒有,則繼續往下走。
  • 第三個階段以此類推,發現有皇后,不慌,不要緊,時光倒流,到第二階段,從新擺放。
  • 第N階段....直到擺出讓每一位皇后滿意的位置。

大概思路就是這樣。測試

初始化

/**
     * 皇后數組
     */
    private int[] queens;
    /**
     * n皇后
     */
    private int n;
    /**
     * 擺法數量
     */
    private int count;

    /**
     * 基於8皇后而衍生的N皇后
     *
     * @param n 皇后的數量
     */
    private SolveNQueens(int n) {
        queens = new int[n];
        this.n = n;
        count = 0;
    }複製代碼

遞歸

雖然代碼很精簡,可是關鍵就在於這個遞歸很差理解。循環裏套遞歸,很巧妙。須要一步一步跟一下就知道了。ui

一維數組存儲的值是皇后的位置(0,n-1)。this

默認是要從頭開始的,須要這麼調用該方法calNQueens(0)spa

private void calNQueens(int row) {
        if (row == n) {
            printQueens(queens);
            return;
        }
        for (int col = 0; col < n; col++) {
            if (isSatisfy(row, col)) {
                queens[row] = col;
                calNQueens(row + 1);
            }
        }
    }複製代碼

是否知足條件

該方法須要判斷本身的橫豎排,左右對角線是否有皇后。code

這裏爲了便於理解,因此循環裏放着三個if。

private boolean isSatisfy(int row, int col) {
//        System.out.println("(" + row + "," + col + ")");
        int leftUp = col - 1;
        int rightUp = col + 1;
        for (int i = row - 1; i >= 0; --i) {
            if (queens[i] == col) return false;
            if (leftUp >= 0 && queens[i] == leftUp) return false;
            if (rightUp < n && queens[i] == rightUp) return false;
            --leftUp;
            ++rightUp;
        }
        return true;
    }複製代碼

打印

private void printQueens(int[] queens) {
        for (int row = 0; row < n; row++) {
            for (int col = 0; col < n; col++) {
                if (queens[row] == col) System.out.print("1 ");
                else System.out.print("0 ");
            }
            System.out.println();
        }
        System.out.println();
        ++count;
    }複製代碼

測試代碼

public static void main(String[] args) {
        int n = 8;
        SolveNQueens solveNQueens = new SolveNQueens(n);
        solveNQueens.calNQueens(0);
        System.out.println("共計" + solveNQueens.count + "種擺法.");
    }複製代碼

測試結果

4皇后


八皇后(這裏是包含了旋轉和對稱的解的解,不然是12種擺法)


end


您的點贊和關注是對我最大的支持,謝謝!
相關文章
相關標籤/搜索