八皇后问题简述
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,
即: 任意两个皇后都不能处于同一行 、同一列或同一斜线上,问有多少种摆法(92)
解题思路:
1) 第一个皇后先放第一行第一列
2) 第二个皇后放在第二行第一列、然后判断是否 OK, 如果不 OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
3) 继续第三个皇后,还是第一列、第二列……直到第 8 个皇后也能放在一个不冲突的位置,算是找到了一个正确解
4) 当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到.
5) 然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4 的步骤
说明:理论上应该创建一个二维数组来表示棋盘,但是实际上可以通过算法,用一个一维数组即可解决问题. arr[8] = {0 , 4, 7, 5, 2, 6, 1, 3}
对应 arr 下标 表示第几行,即第几个皇后,arr[i] = val , val 表示第 i+1 个皇后,放在第 i+1行的第 val+1 列
代码实现:
package dsa.digui;
/**
* 八皇后问题->用递归算法解决
* 1、注意定义一维数组的含义
* 2、注意变量 n、i的含义以及arr[n]和arr[i]的含义
* 3、注意check()和judge()两个方法要连在一起理解,不然可能会不理解(比如如果单独看judge方法,可能会觉得有问题)
*
* @author szw
*/
public class Queen8 {
/**
* 表示一共有八个皇后
*/
int max = 8;
/**
* 定义一个一维数组接收放置各个皇后的一个解法
* 数组下标+1为第几个皇后,即第几行的皇后
* 数组下标对应的value+1为在第几列
* 所以一维数组就可以搞定
*/
int[] arr = new int[max];
/**
* 多少种解法
*/
static int count = 0;
/**
* 判断冲突的次数
*/
static int judgeCnt = 0;
public static void main(String[] args) {
Queen8 queen8 = new Queen8();
//从第一个皇后开始摆
queen8.check(0);
System.out.printf("八皇后一共%d种解法", count);
System.out.println();
System.out.print("打印一下判断冲突的次数:" + judgeCnt);
}
/**
* 注:参数n为数组下标,所以应为第n+1个皇后,也就是第n+1行的皇后
* i则为第i+1列
*
* @param n
*/
public void check(int n) {
//如果n=8,说明8个皇后已经放好
if (n == max) {
print();
return;
}
//
for (int i = 0; i < max; i++) {
//每个皇后(即第n+1个皇后)都先让她在第一列(因为i最初是0),然后判断冲突
arr[n] = i;
//如果不冲突的话
if (judge(n)) {
//则放置下一个皇后(即n+1),开始递归
check(n + 1);
}
}
}
/**
* 注:参数n为数组下标,所以应为第n+1个皇后,也就是第n+1行的皇后
* i则为第i+1列
*
* @param n
* @return
*/
public boolean judge(int n) {
judgeCnt++;
//n为0的话,i<n不成立,不会走循环,即放置第一个皇后根本不会出现冲突的情况
for (int i = 0; i < n; i++) {
//arr[i] == arr[n] 判断是否有皇后在同一列,因为我们规定的一维数组的值就是在第几列
//Math.abs(n - i) == Math.abs(arr[n] - arr[i]) 判断
if (arr[i] == arr[n] || Math.abs(n - i) == Math.abs(arr[n] - arr[i])) {
return false;
}
}
return true;
}
private void print() {
//进入到print,说明已有一种解法,则count++;count代表多少种解法
count++;
//吧一维数组打印出来(即产生的解法->皇后的摆法)
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
测试结果: