问题
在8*8大小的国际象棋棋盘上摆放8个皇后棋子,8个皇后不能互相攻击,即不能在同行同列同斜线上,问共有多少种摆法?
分析
处理此类问题不可暴力枚举,巧用递归算法结构和回溯算法思想,能够快速解决问题。
- 第一个皇后放第一列位置1。
- 第二个皇后放第二列位置1,有冲突,往后放。
- 当三个…
- 放到第n个(n<8),后续还有未放置的皇后(摆放未完成)。这时候就需要回溯了,改变已放置的皇后位置。
- 当找到一种解法,输出序列,摆法加1。跳出当前方法,回到上一级调用,再回溯找其他解法。
代码实现
class Queue8{
//表示八皇后位置的数组
private int[] arr = new int[8];
public int count = 0;
//判断该位置是否可以摆放
private boolean canPlace(int n){
for(int i=0;i<n;i++){
if(arr[i]==arr[n]||Math.abs(n-i)==Math.abs(arr[n]-arr[i])){
return false;
}
}
return true;
}
//摆放方法
public void place(int n){
if(n==arr.length){
print();
count++;
return;
}
for(int i=0;i<arr.length;i++){
arr[n]=i;
if(canPlace(n)){
place(n+1);
}
}
}
//输出方法
public void print(){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
//调用方法
class Main {
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.place(0);
System.out.println(queue8.count);
}
}
结果共打印92种
思考
这个问题看似不好解决,但是代码很简洁。主要就是两个方法
- 判断某个位置能不能放皇后,两个条件判断在不在同一列或者同一斜线,判断在不在同一斜线只需两点间的横纵间距是否相等。
- 摆放方法就是递归调用和回溯的设计,递归就是满足一定条件就调用本身。回溯的体现就是在递归调用本身的同时满足一些条件后跳出当前方法或方法执行完毕,继续执行上一个方法的后续操作。