题解:通过递归回溯思想求解,尝试在棋盘上放皇后,判断尝试将皇后在棋盘上是否会冲突,皇后放置完毕则统计结果。 解题思路就是 通过4x4棋盘放置4皇后推广到nxn 放置n 皇后
private static int count=0;
public int totalNQueens(int n) {
int[][] board=new int[n][n]; //创建棋盘
boolean[][] used=new boolean[n][n]; //用于标记棋盘上皇后的存在
ArrayList<Integer> res=new ArrayList<>();
//用于统计结果,在leetCode官方用 static静态变量统计结果会出错
dfs(board,0,0,used,n,res); //从棋盘第一个位置开始进行皇后放置
return res.size();
}
static void dfs(int[][]board ,int x ,int y,boolean[][] used,int n, ArrayList<Integer> res){ //x代表行,y代表列
if (x== board.length){ //如果x超出棋盘说明皇后放置完毕
int sum = sumArr(board); //对皇后统计
if (sum==n) //棋盘上有n个皇后说明找到一种放置结果
{
res.add(1);
}
return;
}
//不放皇后
if (y<(n-1)){
dfs(board,x,y+1,used,n,res); //列未到最后一列时,尝试下一个位置
}else{
dfs(board,x+1,0,used,n,res); //列到最后一列时,尝试下一行第一个位置
}
//若皇后放置后不受攻击 尝试放
if (is_Attact(board,x,y,used,n)){// 该位置放置皇后是不会产生攻击
board[x][y]=1; //放置
used[x][y]=true; //标记该位置已放置
dfs(board,x+1,0,used,n,res); //尝试放下一行
}
//回溯 恢复状态
board[x][y]=0;
used[x][y]=false;
}
static boolean is_Attact(int[][]board ,int x ,int y,boolean[][] used,int n){ //判断皇后所处位置是否会产生攻击
for (int j = 0; j < board[0].length;j++) { //判断行
if (j==y) continue; //跳过当前放置的判断
if (used[x][j]==true)return false; //皇后攻击
}
for (int i = 0; i <board.length ; i++) { //判断列
if (i==x) continue; //跳过当前放置的判断
if (used[i][y]==true) return false; //皇后攻击
}
int t_x=x;
int t_y=y;
for (int i = -(n-1); i <= n-1; i++) { //判断左下角
if ((x+i)==t_x && (y-i)==t_y)
continue; //跳过当前放置的判断
if (x+i>=0 && x+i <=n-1 && y-i>=0 && y-i <=n-1) //确保数组不会越界
if (used[x+i][y-i] ==true)
return false; //皇后攻击
}
for (int i = -(n-1); i <= n-1; i++) { //判断右下角
if ((x+i)==t_x && (y+i)==t_y)
continue; //跳过当前放置的判断
if (x+i>=0 && x+i <=n-1 && y+i>=0 && y+i <=n-1) //确保数组不会越界
if (used[x+i][y+i] ==true)
return false; //皇后攻击
}
return true; //皇后不会攻击
}
static int sumArr(int[][] a){
int s=0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j <a[0].length; j++) {
s+=a[i][j];
}
}
return s;
}