八皇后问题是一个古来而著名的问题,该问题是19世纪著名的数学家高斯同窗提出来的。在8*8的国际象棋上摆放八个皇后,使其不能互相的攻击,也就是说,任意的两个皇后不能放在同一行或则是同一个列或者是同一个对角线上,问有多少个摆放的方法
本算法的思路是按行来规定皇后位置,第一行放置一个皇后,第二行放置一个皇后, 第N行也放置一个皇后… 这样, 能够保证每行都有一个皇后,那么各行的皇后应该放置在那一列呢, 算法经过循环来完成,在循环的过程当中, 一旦找到一个合适的列,则该行的皇后位置肯定,则继续进行下一行的皇后的位置的肯定。因为每一行肯定皇后位置的方式类似,因此可使用递归法。一旦最后 一行的皇后位置肯定,则能够获得一组解。找到一组解以后, 以前肯定皇后应该放置在哪一列的循环其实才进行了一轮循环的, 算法经过该循环遍历全部的列,以此肯定每一行全部可能的列的位置。在从一轮循环进入下一轮循环以前,算法须要清除在上一轮被标记为不可放置皇后的标记,也就是回溯。由于进入下一轮循环以后,同一行的皇后的列的位置会发生了变化,以前被标记为不可放置皇后的列和正反对角线位置都已经失效。 java
public class EightQueenSolver { private int QUEEN_COUNT = 0; // 皇后的默认数量 private int[][] Queencount;// 分配8X8的数组,充当棋盘,存放皇后 private int resultCount = 0;// 记录皇后的放置方法的总数 private int[] Queenplace;// 对于索引n, Queenplace[n]表示第n行的皇后放置位置是第Queenplace[n]列 public EightQueenSolver(int n) { this.QUEEN_COUNT = n; this.resultCount = 0; this.Queencount = new int[QUEEN_COUNT][QUEEN_COUNT]; Queenplace = new int[QUEEN_COUNT]; } public void putQueen() { putQueen(0); } private void putQueen(int row0) { int row = row0;// 行标 for (int column = 0; column < QUEEN_COUNT; column++)// column表示列标,该层循环的做用是用于询问第row行,第column列是否能够放置皇后 { if (Queencount[row][column] == 0)// 若是第row行、第column列能够放皇后 { for (int nextRow = row + 1; nextRow < QUEEN_COUNT; nextRow++)// 该层for循环的做用是使其斜下方和正下方不为0 { //将不一样行的同一列(正下方)标记为非零,表示不能再在该列放置皇后了 Queencount[nextRow][column]++; //经过该层循环将第row行、第column列的正对角线上的位置标记为非零,表示不能在这些位置放置皇后 if (column - nextRow + row >= 0) { Queencount[nextRow][column - nextRow + row]++; } //经过该层循环将第row行、第column列的反对角线上的位置标记为非零,表示不能在这些位置放置皇后 if (column + nextRow - row < QUEEN_COUNT) { Queencount[nextRow][column + nextRow - row]++; } } // 记录下第row行第column列放置了皇后 Queenplace[row] = column; // 若是各行都放置了皇后,也就是说若是皇后已放满,打印出皇后布局 if (row == QUEEN_COUNT - 1) { printQueen(++resultCount); } else // 不然递归继续排列下一行皇后 { putQueen(row + 1); } for (int rows = row + 1; rows < QUEEN_COUNT; rows++)// 回溯,使得在第row行的皇后不放在第column列,那放置在那一列? // 答案是经过该算法的最外层循环,利用最外层for循环将皇后放在这一行的其余列 { //既然第row行、第column列不放置皇后了,则须要恢复正下方的不可用标记,将不一样行的同一列的非零标记还原,也即恢复该位置的正下面的标记 Queencount[rows][column]--; //还原第row行、第column列的正对角线上的位置标记 if (column - rows + row >= 0) { Queencount[rows][column - rows + row]--; } //还原第row行、第column列的反对角线上的位置标记 if (column + rows - row < QUEEN_COUNT) { Queencount[rows][column + rows - row]--; } } } } if (row == 0) { System.out.println(QUEEN_COUNT + "皇后问题共有" + resultCount + "个解."); } } private void printQueen(int size)// 打印皇后布局 { System.out.println(QUEEN_COUNT + "皇后的第" + size + "个解是:"); System.out.println(); for (int row = 0; row < QUEEN_COUNT; row++) { for (int column = 0; column < QUEEN_COUNT; column++) { System.out.print(Queenplace[row] == column ? " * " : " - "); } System.out.println(); } System.out.println(); } public static void main(String[] args) { EightQueenSolver eq = new EightQueenSolver(8); eq.putQueen(); } }