问题描述
在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
问题分析
先将第一个皇后放在第一行第一列,然后将第二个皇后放在第二行第一列,判断一下第二个皇后与前面所有的皇后是否在同一列或同一斜线上,若在则将第二个皇后放在下一列,继续判断,若不在则放下一个皇后
…
直到八个皇后放完,就是一种解法。接着再把上一个皇后挪到下一列,看是否有解。
代码实现
回溯法
import java.util.Arrays;
public class EightQueen {
private static int max = 8; //皇后数,棋盘行列
/**
* 一行只有一个皇后,所以用一维数组即可
* 索引代表行,值代表列
*/
private static int[] queen = new int[max];
private static int cut; //记录八皇后的摆法数量
public static void main(String[] args) {
queen(0);
System.out.printf("八皇后共有%d种摆法",cut);
}
/**
* 放置皇后
* @param n 代表行数
*/
private static void queen(int n) {
if (n == max) { //行数达到最大,代表八个皇后已经放下了
print(); //打印棋盘
cut++;
return;
}
for (int i = 0; i < max; i++) { //皇后在这一行的所有位置都试一次
queen[n] = i;
if (judge(n)) { //如果这个位置可以放皇后,则去下一行放置皇后
queen(n + 1);
}
}
}
/**
* 判断该位置是否能放皇后
*/
private static boolean judge(int n) {
for (int i = 0; i < n; i++) { //枚举前面所有的皇后,看是否有在同一列或同意斜线
if (queen[i] == queen[n] || Math.abs(i - n) == Math.abs(queen[i] - queen[n])) {
//值相等代表在同一列,行差和列差相等代表在同一斜线
return false;
}
}
return true;
}
/**
* 打印棋盘
*/
private static void print() {
System.out.println(Arrays.toString(queen));
for (int i = 0; i < max; i++) {
for (int j = 0; j < max; j++) {
if (j == queen[i]) {
System.out.print("1 ");
} else {
System.out.print("0 ");
}
}
System.out.println();
}
System.out.println();
}
}
结果视图