数据结构与算法
一,八皇后
1,简介:
八皇后问题: 一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
图示:
2,分析:
- 第一个皇后先放第一行第一列;
- 第二个放第二行第一列,判断是否满足条件,如果不满足,放到第二列,第三列…依次把所有列都放完,找到一个合适的;
- 继续放第三个皇后,还是第一列,第二列…也放在一个不冲突的位置,走完之后找到一个正确解;
- 得到一个正确解之后,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一例的所有正确解全部得到;
- 然后回头继续将第一个皇后放到第二列,依次循环执行上面步骤;
理论上创建一个二维数组实现八皇后,但是通过分析可以使用一维数组解决;如上图可用数组arr[8]={2,4,7,3,0,6,1,5}来表示,数组下标表示行-1,对应值表示列-1;
3,八皇后代码实现:
package com.recursion;
/**
* @param
* @Author: AaNeei
* @Date: 2019/6/15 21:48
* @Description: 游学网
* @throws:
*/
public class EightQueen {
private static final int MAX = 8;
int[] queenArr = new int[MAX];
private static int count = 0;
public static void main(String[] args) {
EightQueen queen = new EightQueen();
queen.check(0);
System.out.println("八皇后问题共有:" + count + "种解法");
}
public void check(int n) {
//8个皇后排完了
if (n == MAX) {
print();
return;
}
for (int i = 0; i < MAX; i++) {
//把皇后放到第n行的第i列
queenArr[n] = i;
//摆好判断是否冲突
if (judge(n)) {
//不冲突,递归放入
check(n + 1);
}
}
}
//判断当前皇后是否存在冲突
public boolean judge(int n) {
for (int i = 0; i < n; i++) {
//queenArr[i]==queenArr[n]表示在同一列
//Math.abs(n-i)==Math.abs(queenArr[n]-queenArr[i])表示在同一斜线
if (queenArr[i] == queenArr[n] || Math.abs(n - i) == Math.abs(queenArr[n] - queenArr[i])) {
return false;
}
}
return true;
}
//打印
public void print() {
count++;
for (int i : queenArr) {
System.out.print(i + " ");
}
System.out.println();
}
}
注: 每次得到一个解法之后都会回溯前面放过的皇后,检查是否有新的解法,最终得到92种解法;