八皇后问题是由国际象棋手马克斯-贝瑟于1848年提出的问题,是回溯算法的经典案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
答案是92种,一维数组和二维数组都可以用来解决该问题,在这里使用一维数组模拟解决该问题,其中一维数组有八个元素,每个元素的位置标号代表第几行,而每个元素的值代表是在该行的第几列。
例如:0 6 4 7 1 3 5 2 就代表八个皇后被摆放在(0,0),(1,6),(2,4),(3,7),(4,1),(5,3),(6,5),(7,2)八个位置
1.基本思路
先在某行的第一列位置放置一个皇后,再和其他所有已经放置的进行比较,当不冲突时就去下一行放置下一个皇后,否则放于这一行的第二列,再判断是否符合条件。
假如某行的八个列都不能放置,那么就回溯至上一层,调整上一层的皇后位置,如此递归调整,直到所有的8个皇后符合条件。
2.代码实现
2.1 Queue8类
package 八皇后问题;
/**
* @Classname Queue8
* @Description 使用一维数组解决8皇后问题
* @Date 2022/6/16 21:09
* @Created by jiawen
*/
public class Queue8 {
private int max = 8;
private int[] arr = new int[max];
int count = 0;
private boolean checkConflict(int n) {//false代表冲突;true代表不冲突
for (int i = 0; i < n; i++) {
if (arr[i] == arr[n] || Math.abs(i - n) == Math.abs(arr[i] - arr[n])) {
//无需考虑是否在同一行,当使用一维数组实现的时候,任何两个皇后都不会在同一行,只需判断是否同一列或者对角
//Math.abs(i - n) == Math.abs(arr[i] - arr[n]),类似于斜率,左边为行差,右侧为列差,当二者相等时,证明处于斜对角
return false;
}
}
return true;
}
//queueNumber代表放置的第几个queue
void placeQueue(int queueNumber) {
if (queueNumber == max) {
//注意,这里是queueNumber == max(放置数=8)时结束方法,
//当放置数=8时证明这是在放置第九个皇后,那么这个皇后无需放置,直接return
listArr();
return;
}
for (int i = 0; i < max; i++) {
//i代表的是放置的列,由于我们使用一维数组代替,所以arr的某个元素的数值就代表第几列,该数值加1,就代表在这一行移动了一列
arr[queueNumber] = i;//一开始i为0,证明在第0列
if (checkConflict(queueNumber)) {//如果不冲突,在这个放置的基础上放置下一个
placeQueue(queueNumber + 1);
}
}
}
private void listArr() {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
count++;
}
}
2.2 主方法
package 八皇后问题;
/**
* @Classname DemoTest
* @Description TODO
* @Date 2022/6/16 21:50
* @Created by jiawen
*/
public class DemoTest {
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
System.out.println("===============");
queue8.placeQueue(0);
System.out.println("===============");
System.out.println("一共" + queue8.count + "种解法");
}
}
3. 运行结果
===============
0 4 7 5 2 6 1 3
0 5 7 2 6 3 1 4
0 6 3 5 7 1 4 2
0 6 4 7 1 3 5 2
1 3 5 7 2 0 6 4
1 4 6 0 2 7 5 3
1 4 6 3 0 7 5 2
1 5 0 6 3 7 2 4
1 5 7 2 0 3 6 4
1 6 2 5 7 4 0 3
1 6 4 7 0 3 5 2
1 7 5 0 2 4 6 3
2 0 6 4 7 1 3 5
2 4 1 7 0 6 3 5
2 4 1 7 5 3 6 0
2 4 6 0 3 1 7 5
2 4 7 3 0 6 1 5
2 5 1 4 7 0 6 3
2 5 1 6 0 3 7 4
2 5 1 6 4 0 7 3
2 5 3 0 7 4 6 1
2 5 3 1 7 4 6 0
2 5 7 0 3 6 4 1
2 5 7 0 4 6 1 3
2 5 7 1 3 0 6 4
2 6 1 7 4 0 3 5
2 6 1 7 5 3 0 4
2 7 3 6 0 5 1 4
3 0 4 7 1 6 2 5
3 0 4 7 5 2 6 1
3 1 4 7 5 0 2 6
3 1 6 2 5 7 0 4
3 1 6 2 5 7 4 0
3 1 6 4 0 7 5 2
3 1 7 4 6 0 2 5
3 1 7 5 0 2 4 6
3 5 0 4 1 7 2 6
3 5 7 1 6 0 2 4
3 5 7 2 0 6 4 1
3 6 0 7 4 1 5 2
3 6 2 7 1 4 0 5
3 6 4 1 5 0 2 7
3 6 4 2 0 5 7 1
3 7 0 2 5 1 6 4
3 7 0 4 6 1 5 2
3 7 4 2 0 6 1 5
4 0 3 5 7 1 6 2
4 0 7 3 1 6 2 5
4 0 7 5 2 6 1 3
4 1 3 5 7 2 0 6
4 1 3 6 2 7 5 0
4 1 5 0 6 3 7 2
4 1 7 0 3 6 2 5
4 2 0 5 7 1 3 6
4 2 0 6 1 7 5 3
4 2 7 3 6 0 5 1
4 6 0 2 7 5 3 1
4 6 0 3 1 7 5 2
4 6 1 3 7 0 2 5
4 6 1 5 2 0 3 7
4 6 1 5 2 0 7 3
4 6 3 0 2 7 5 1
4 7 3 0 2 5 1 6
4 7 3 0 6 1 5 2
5 0 4 1 7 2 6 3
5 1 6 0 2 4 7 3
5 1 6 0 3 7 4 2
5 2 0 6 4 7 1 3
5 2 0 7 3 1 6 4
5 2 0 7 4 1 3 6
5 2 4 6 0 3 1 7
5 2 4 7 0 3 1 6
5 2 6 1 3 7 0 4
5 2 6 1 7 4 0 3
5 2 6 3 0 7 1 4
5 3 0 4 7 1 6 2
5 3 1 7 4 6 0 2
5 3 6 0 2 4 1 7
5 3 6 0 7 1 4 2
5 7 1 3 0 6 4 2
6 0 2 7 5 3 1 4
6 1 3 0 7 4 2 5
6 1 5 2 0 3 7 4
6 2 0 5 7 4 1 3
6 2 7 1 4 0 5 3
6 3 1 4 7 0 2 5
6 3 1 7 5 0 2 4
6 4 2 0 5 7 1 3
7 1 3 0 6 4 2 5
7 1 4 2 0 6 3 5
7 2 0 5 1 4 6 3
7 3 0 2 5 1 6 4
===============
一共92种解法