首先这是我第一次写博客,可能解说的不会太详细,尽量用代码注释补全吧。
n皇后问题是一个很经典的dfs问题,相信每个学习算法的小伙伴都会碰到这个算法,我也是写过了很多回,有用过二维数组的也用过一维的,这次将自己的学习经验分享给同样因为这个问题深受困扰的小伙伴们。
题目
在一张N∗N的国际象棋棋盘上,放置N个皇后,使得所有皇后都无法互相直接攻击得到,(皇后可以直接攻击到她所在的横行,竖列,斜方向上的棋子),现在输入一个整数N,表示在N∗N的棋盘上放N个皇后,请输出共有多少种使得所有皇后都无法互相直接攻击得到的方案数。
输入
一个整数N,代表皇后的个数
输出
输出方案数
样例输入1
4
样例输出1
2
样例输入2
8
样例输出2
92
首先我们需要输入一个数N,我们通过一个一维数组queue来表示棋盘,我们用这个queue数组的
下标来表示棋盘是第几行,用数组中的元素来表示是棋盘的第几列。
对于queue数组,当queue[1] = 3 时,证明我在棋盘的第一行第三列放置了一个皇后,因为是一维
数组,我们在递归放置皇后的时候并不需要去储存上一个状态之类的操作,我们只需要通过回溯来
更改数组内的元素实现在同一行的不同位置进行放置皇后的操作,并判断此操作是否合法。
相对于二维数组的做法而言,我们只需要判断数组下标和数组元素是否符合皇后的防治法则。
综上所述,我们需要创建一个dfs方法用于实现放置皇后操作,再创建一个chcek方法用来判断当前放置的皇后是否会被攻击
因为是第一次写,也不怎么会说,接下来上代码
import java.util.*;
//n皇后问题
public class Main {
Scanner in = new Scanner(System.in);
//接收数据 N
int N = in.nextInt();
//这是我们的棋盘,为了更容易看懂,我们忽略掉下标0的位置,以后操作都从第1行开始
int[] queue = new int[N+1];
//方案数
int n = 0 ;
/*
首先我们写一个dfs的函数,x代表当前要放置皇后的行数,通过递归往x+1行去执行放置皇后的操作
*/
void dfs(int x) {
if(x>N){//这是边界,说明我们已经放完了N行的皇后找到了答案
n++;
return;
}
for(int i = 1 ; i<=N ; i++){
queue[x] = i ; //在第x行的第i列放置一个皇后
if(check(x)){//判断第x行的皇后是否与前面的起冲突
dfs(x+1);//说明合法,递归往x+1行放置皇后
}
}
}
boolean check(int x){
//从第一行到第x-1行 逐行判断是否合法
for(int i = 1 ; i<x ; i++){
//这里为了更清楚的展示,将判断分开
if(queue[x]==queue[i]){//说明在同一列上,会被攻击
return false;
}
//当第行与行的差值等于列与列的差值时,说明在同一斜线(可以自己画图证明一下)
if(Math.abs(queue[x]-queue[i])==Math.abs(x-i)){
return false;
}
}
return true;
}
public static void main(String[] args) {
Main m = new Main();
m.dfs(1);//调用方法,从第1行放置皇后
System.out.println(m.n);//输出方案数
}
}
版权归原作者 系阿韦阿 所有, 如有侵权,请联系我们删除。