八皇后问题
在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
通过回溯法(递归)可以解决此问题,经过测试,共有92种摆法。
java实现
思路:
- 定一个一维数组,数组大小与皇后数量一致,数组中的每个元素对应一个皇后,数组中的下标对应皇后的行,值对应皇后的列,例如{6 1 5 2 0 3 7 4}, 6说明第一个皇后的坐标为(0,6)
- 自定义皇后的数量queenCount, 对应棋盘大小为 queenCount * queenCount,棋盘大小必须大于2*2
- 定义totalCount,用于统计在当前大小的棋盘下,一共存在多少种摆放策略
- 步骤
4.1 从第一个皇后开始摆放,若摆放了queenCount个皇后,说明一种策略摆放完毕,输出每个皇后的下标,摆放策略+1
4.2 分情况讨论
(1)判断当前皇后的坐标是否与之前的皇后坐标冲突(在同一行同一列或者同一条斜线上),若不冲突继续递归摆放下一个皇后。
(2)若冲突,将皇后的列+1,继续判断当前坐标是否可用。
代码如下
/**
* 回溯法解决八皇后问题
* 1. 定一个一维数组,数组大小与皇后数量一致,数组中的每个元素对应一个皇后
* 数组中的下标对应皇后的行,值对应皇后的列,例如{6 1 5 2 0 3 7 4}, 6说明第一个皇后的坐标为(0,6)
* 2. 自定义皇后的数量queenCount, 对应棋盘大小为 queenCount * queenCount,棋盘大小必须大于2*2
* 3. 定义totalCount,用于统计在当前大小的棋盘下,一共存在多少种摆放策略
* 4. 步骤
* 4.1 从第一个皇后开始摆放,若摆放了queenCount个皇后,说明一种策略摆放完毕,输出每个皇后的下标,摆放策略+1
* 4.2
* (1)判断当前皇后的坐标是否与之前的皇后坐标冲突(在同一行同一列或者同一条斜线上),若不冲突继续递归摆放下一个皇后。
* (2)若冲突,将皇后的列+1,继续判断当前坐标是否可用
*/
public class BackTrace {
private int[] arrayQueen;
private int queenCount;
static int totalCount = 0;
public BackTrace(int size){
if (size < 3){
throw new RuntimeException("宫格的大小必须大于等于3!");
}
this.queenCount = size;
this.arrayQueen = new int[size];
}
private void addQueen(int n){
if (n == queenCount){//全部放满,直接输出
totalCount ++;
print();
return;
}
for (int i =0; i < queenCount; i ++){
arrayQueen[n] =i;
if (!isConflict(n)){
addQueen(n + 1);
}
}
}
/**
* 打印每种放法
*/
private void print(){
for (int j =0 ; j < arrayQueen.length; j++){
System.out.print(arrayQueen[j] + " ");
}
System.out.println("");
}
/**
* 判断是否有皇后在同一行同一列或者同一条斜线上
*/
private boolean isConflict(int n){
for (int i =0; i < n; i ++){
if (arrayQueen[i] == arrayQueen[n] || Math.abs(n - i) == Math.abs(arrayQueen[n] - arrayQueen[i])){
return true;//有皇后和当前皇后处于同一列
}
}
return false;
}
public static void main(String[] args) {
BackTrace trace = new BackTrace(8);
trace.addQueen(0);
System.out.println("总共有:" + totalCount + "种摆法");
}
}
测试结果:
image.png
验证:
以 7 2 0 5 1 4 6 3 为例,通过八皇后小游戏进行验证(最下边一行表示第一行),结果正确。
VmAUmYuk8y.jpg
欢迎留言,我们一起成长~~