1. 程式人生 > >Java遞迴解決n皇后問題

Java遞迴解決n皇后問題

題目

八皇后問題是一個以國際象棋為背景的問題:如何能夠在 8×8 的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?這道題目也可以稍微延伸一下,變為 N×N的棋盤上放置N個皇后,其他條件相同。 下面介紹一種比較簡單易懂的實現方式。

程式碼

import java.util.ArrayList;
import java.util.List;

/**
 * Created by GuanDS on 2018/9/20.
 */
public class Queen {

    public static void main(String[] args) {
        long currentTime = System.currentTimeMillis();
        int n = 8;
        Queen queen = new Queen();
        short[] cols = queen.getNewShort(n); // 初始化陣列, 存放列, 不能為預設值, 設定為2*n
        queen.putQueen(new short[n][n], (short) 0, cols, cols.clone(), cols.clone());
        System.out.println(n + "皇后, 共 " + queen.list.size() + " 種情況, 用時: " + (System.currentTimeMillis() - currentTime) + "ms");
    }

    private List<short[][]> list = new ArrayList<>();

    /**
     * 遞迴存放皇后
     * @param queens 歷史陣列
     * @param c 當前第c個
     * @param cols 以存放皇后的列序
     * @param rowAddCols 行序+列序
     * @param rowSubCols 行序-列序
     */
    private void putQueen(short[][] queens, short c, short[] cols, short[] rowAddCols, short[] rowSubCols) {
        for (short i = 0; i < queens.length; i++) {
            if (isContains(cols, i)
                    || isContains(rowAddCols, (short) (c + i))
                    || isContains(rowSubCols, (short) (c - i))) {
                continue;
            }
            short[][] tqueens = copy(queens);
            short[] tcols = cols.clone();
            short[] trowAddCols = rowAddCols.clone();
            short[] trowSubCols = rowSubCols.clone();
            tqueens[c][i] = 1;
            tcols[c] = i;
            trowAddCols[c] = (short) (c + i);
            trowSubCols[c] = (short) (c - i);

            if (c >= queens.length - 1) {
                list.add(tqueens);
            } else {
                putQueen(tqueens, (short) (c + 1), tcols, trowAddCols, trowSubCols);
            }
        }
    }

    // 判斷陣列中是否包含某元素
    private boolean isContains(short[] array, short n) {
        for (short i : array) {
            if (i == n) {
                return true;
            }
        }
        return false;
    }

    // 初始化一個新的short陣列
    private short[] getNewShort(int n) {
        short[] shorts = new short[n];
        for (int i = 0; i < n; i++) {
            shorts[i] = (short) (2 * n);
        }
        return shorts;
    }

    // copy二維short陣列
    private static short[][] copy(short[][] array) {
        short[][] result = new short[array.length][array[0].length];
        for (int m = 0; m < array.length; m++) {
            for (int n = 0; n < array[0].length; n++) {
                result[m][n] = array[m][n];
            }
        }
        return result;
    }

}