n皇后问题就是在n*n的棋盘上放置n个皇后,使她们之间不在同一行同一列,且不在同一个对角线上
问:共有多少种摆法?
首先分析问题:
直观的来说,我们可以想到直接使用暴力回溯出符合条件的解
如何暴力?
从第一行开始以此遍历每一个格子,再继续向上层遍历
比如:对于一个4*4的棋盘,可以先确定第一行的[1,1],再继续遍历第二行,确定第二行的位置,重复此过程
确定了回溯的过程,那么接下来就只需要一个判断函数,即判断当前格子是否符合条件
下面开始实现:
首先明确的是,对于每一行来说,都会有一个皇后,所以可以定义一个一维数组,
用 r[i] = j 来表示第i行j列放置了一个皇后。
对于判断函数check(int x,int y)
x,y分别代表行数和列数,因为只要在当前行找到一个符合条件的位置,我们就会立刻进入下一行继续寻找,所以在判断条件时只需要考虑当前列、当前的左对角线,当前的右对角线是否已经被占用,而不需要考虑当前行是否已经存在皇后。
对于当前的左右两条对角线的判定,我们只需要通过下标就可以完成判定。
因为对于左对角线来说,在同一条直线上的下标的差都是相等的
对于右对角线来说,在同一条直线上的合都是相等的。
代码实现
static int n;//棋盘的大小
static int[]r;//皇后的位置
static int count =0;//记录可能的结果
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
n = in.nextInt();
r =new int[n+1];
dfs(1);
System.out.println(count);
}
public static void dfs(int row){
if(row ==n+1)//棋盘的每一行已经放置完毕
{
count++;
return;
}
for(int i=1;i<=n;i++){
if(check(row,i)){
//如果当前符合条件,开始深搜
r[row] = i;
dfs(row+1);
//不要忘记回溯回来哦
r[row] =0;
}
}
}
/**
* 判断当前位置是否符合放置条件
* @param x 行数
* @param y 列数
* @return
*/
public static boolean check(int x,int y){
for(int i=1;i
if(r[i] == y){
//如果此列已经在前几行放置过了
return false;
}
if(x+y == i+r[i]){
return false;
}
if(x-y == i-r[i]){
return false;
}
}
return true;
}