一、问题描述
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法(92)。
二、解题思路
- 第一个皇后先放第一行第一列
- 第二个皇后从第二行第一列开始判断是否可行,不可行放在第二列、第三列以此类推......
- 继续第三个皇后,还是第一列、第二列……直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
- 当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到
- 然后回头继续第一个皇后放第二列,后面继续循环执行1、2、3、4的步骤
三、实现思路
- 先创建一个值表示到底有多少个皇后;定义一个数组array,用于保存皇后到底保存在哪个位置;(这里不采用二维数组的方式,而是使用一维数组,放置第i行皇后在哪列)
- 写一个方法,把皇后码放的位置显示出来
- 写一个方法,放置第n个皇后时,判断该皇后是否位置合法(是否同行、同列、同斜线),判断是否是同一条斜线可以通过判断斜率是否为1来实现
- 写一个放皇后的方法,从第0个皇后开始放,从第1列开始放,如果冲突就放下一个位置,如果不冲突就继续放下一个,这样递归下去。
四、代码
public class Queens {
int max = 8; //一共8个皇后,定义初始值
int[] array = new int[max];
static int count=0;
public static void main(String[] args) {
Queens queens = new Queens();
queens.put(0);
System.out.println(count);
}
//结果输出方法
private void print() {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
}
System.out.println();
}
//检查放到第n个皇后时,是否与之前的皇后冲突
private boolean check(int n) {
for (int i = 0; i < n; i++) {
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[i] - array[n])) {
return false;
}
}
return true;
}
//放置第n个皇后
private void put(int n){
if (n == max){ //因为下标是从0开始的,所以当n=8时代表再放就是第九个皇后了,就是已经放完了8个。直接打印结果即可。
count++;
print();
return;
}
for (int i=0;i<max;i++){
array[n] = i;//先把这个皇后放到此行的第一个位置
if (check(n)){//检查放第n个皇后时是否冲突,不冲突的话就继续放置第n+1个。
put(n+1);
}
}//如果冲突了就继续执行 array[n] = i这就相当于这一行的这个位置是不行的,我们要试试下个位置了
}
}
复制代码