N皇后是常见的算法题,那我们如何去判断当前N皇后是否存在相互攻击情况呢?
判断N皇后不能相互攻击需要满足一下三种条件:
- 任意两个皇后不能在同一行
- 任意两个皇后不能在同一列
- 任意两个皇后不能在同一条对角线[主副对角线]上
判断步骤
- 借助辅助数组locations[N][N]来记录皇后的位置,每初始化一行(根据每一行输入的皇后位置)就记录一次
- 记录的时候我们就借助上述条件来进行初始化,将当前皇后所在位置的行、列、主副对角线都记录(假设都置为1)
- 每一行输入的皇后位置都会与辅助数组locations判断。
如果当前输入行存在2个及其以上的皇后,那么就直接置为true(表示会进行相互攻击);
如果当前皇后的位置在辅助数组locations中,即realLocations[i][j]==locations[i][j],说明当前位置不能放置皇后了,直接置为true(表示会进行相互攻击)
因此,根据以上步骤可以写出以下代码
import java.util.Scanner;
public class NQueen {
public static boolean res = false;//不能相互攻击
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int[][] locations = new int[N][N];
int[][] realLocations = new int[N][N];
locations[0][1] = 1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
realLocations[i][j] = scanner.nextInt();
}
}
for (int i = 0; i <N; i++) {
initLocations(realLocations,locations,i);
}
System.out.println(res);
}
public static void initLocations(int[][] realLocations,int[][] locations,int i){
int count = 0,col = 0;
for (int j = 0; j < locations.length; j++) {
if (realLocations[i][j]==1){
count++;
col = j;//记录该行皇后出现的位置
}
}
if (count>1||locations[i][col]==1){//如果该行出现的皇后次数大于1或者当前位置已经放置皇后 则可以相互攻击
res = true;
return;
}
for (int j = 0; j <locations.length ; j++) {
locations[i][j] = 1;//该行置为1 表示之后无法在该行放置皇后
locations[j][col] = 1;//该列设置为1 表示之后无法在该列放置皇后
}
for (int j = 0; j < col; j++) {
locations[j][col-j]=1;//副对角线置为1 表示之后无法在该副对角线上放置皇后
}
for (int k=col;k<locations.length;k++){
if (i<locations.length)
locations[i][k]=1;//主对角线置为1 表示之后无法在该主对角线上放置皇后
i++;
}
}
}
用例测试
8
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0
true // 会相互攻击 最后一行和倒数第二行存在副对角线上攻击情况
8
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 1 0 0 0
false // 不会相互攻击