八皇后问题

八皇后问题

八皇后问题

1. 八皇后问题介绍

八皇后问题是一个经典的回溯算法思想求解的问题,该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出的:在8×8的国际象棋棋盘上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,求共有多少种摆法。

2. 回溯算法求解八皇后问题的思路

第一个皇后先放在第一行第一列;

第二个皇后放在第二行第一列,先判断是否冲突,若冲突,则继续往后放,依次把所有列都放完,找到合适的位置;

继续按照上一个步骤放置其余的皇后,直至8个皇后都放置在互不冲突的位置,(此过程中可能发生回溯到步骤二),即找到了一个正确解;

当得到一个正确解时,退回到上一个栈,开始回溯,将第一个皇后放在第一列的所有正确解求出(即第一个皇后仍放在第一列不变,其他皇后继续往后摆);

然后回头继续第一个皇后放第一行第二列,继续执行上述步骤。

说明:

理论上应该创建一个二维数组来表示棋盘,但实际上可以通过算法,用一个一维数组即可解决问题:arr[8] = {0, 4, 7, 5, 2, 6, 1, 3}

arr数组的下标表示皇后所在的行(也即第n+1个皇后),arr数组的值表示皇后所在的列

eg.arr[3] = 5就表示第4个皇后在第4行第6列

函数解释:

judge(int n)方法:

用于判断当前放置的第n+1个皇后是否与前面放置的所有皇后冲突

判断是否在同一列:arr[i] == arr[n]

判断是否在同一斜线:Math.abs(i - n) == Math.abs(arr[i] - arr[n])

通过判断斜率是否为1判断是否在同一斜线上,即行差的绝对值是否等于列差的绝对值

check(int n)方法:

用于放置当前的第n+1个皇后(n从0开始计数,因此当n == 8时,已经准备放置第9个皇后,即前8个皇后已经正确放置,退出程序即可)

每一个当前放置的皇后都需要放置到该行的每一列并与前面放置的皇后进行judge,因此需要一个for循环,若不冲突才放置下一个

进一步地,上步放置下一个皇后时即开始了递归过程,每一次check都经历一个for循环。当某一次放置的for循环走完时仍冲突,即回退到了上一个栈,继续执行上一次放置时的for循环(即i++往后面的列摆),即完成回溯的过程

3. 代码实现

package com.algorithm;

/**

* @author SnkrGao

* @create 2023-04-08 22:11

*/

public class EightQueens {

int queenNum = 8;

int[] arr = new int[queenNum];

static int count = 0;

public static void main(String[] args) {

EightQueens eightQueens = new EightQueens();

eightQueens.check(0);

System.out.println("共有"+count+"种解法");

}

// 放置第n+1个皇后

// 需要注意每一次check递归时,都会执行for循环,因此会产生回溯

private void check(int n) {

if (n == queenNum) { // 递归终止条件,表示前8个皇后都放置完成,即退出程序

print();

return;

}

for (int i = 0; i < queenNum; i++) { // 此处i < 8表示放置在每一行的不同列

// 循环开始时先将第n+1个皇后放置在第一列的位置

arr[n] = i;

// 判断第n+1个皇后放置在i列时与前面所有皇后是否冲突

if (judge(n)) {

// 若不冲突开始放置下一个皇后,即开始递归

check(n + 1);

}

// 若冲突,则继续执行arr[n] = i++,将该皇后往后摆一列

}

}

// 判断当前放置的第n+1个皇后是否与前面的皇后位置冲突

private boolean judge(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;

}

// 输出arr数组,即皇后摆放位置的每一种解法

private void print() {

count++;

for (int i = 0; i < arr.length; i++) {

System.out.print(arr[i] + "\t");

}

System.out.println();

}

}

相关推荐

qq靓号怎么申请 qq靓号申请方法
365bet英国

qq靓号怎么申请 qq靓号申请方法

📅 07-02 👁️ 8456
wow刻符者之厅在哪里
365bet英国

wow刻符者之厅在哪里

📅 10-09 👁️ 5332