package leecode;
import java.util.*;
/**
* 51. N 皇后
*
* n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
* (皇后可以攻击同一行 同一列 左上 左下 右上 右下)
*
* 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
*
* 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
*
*
* @author Tang
* @date 2021/12/9
*/
public class SolveNQueens {
List<List<String>> result = new ArrayList<>();
char[][] chessboard;
public List<List<String>> solveNQueens(int n) {
//准备一个n*n的棋盘
//初始化全都是.
chessboard = new char[n][n];
for(int i = 0; i < chessboard.length; i++) {
Arrays.fill(chessboard[i], '.');
}
track(0);
return result;
}
private void track(int rowIndex) {
//结束条件 所有皇后都已经选完
if(rowIndex == chessboard.length) {
List<String> chooseList = new ArrayList<>();
for (char[] chars : chessboard) {
StringBuilder s = new StringBuilder();
for (char c : chars) {
s.append(c);
}
chooseList.add(s.toString());
}
result.add(chooseList);
return;
}
for(int i = 0; i < chessboard[rowIndex].length; i++) {
//递归前做出选择 选出皇后落在该行中的位置
if(!check(rowIndex, i)) {
continue;
}
chessboard[rowIndex][i] = 'Q';
//执行递归 去玩下一行
track(rowIndex + 1);
//递归后撤销选择
chessboard[rowIndex][i] = '.';
}
}
/**
* 判断某个点能否放皇后
* 也就是说该点的行,列,左上,右上是否唯一
*
* @param rowIndex 当前元素是第几行
* @param columnIndex 当前元素是第几列
* @return
*/
private boolean check(int rowIndex, int columnIndex) {
//行不需要判断 天然唯一
//列是否唯一
for(int i = 0; i < chessboard.length; i++) {
if(chessboard[i][columnIndex] == 'Q') {
return false;
}
}
//左上
int i = rowIndex-1;
int j = columnIndex-1;
while(i >= 0 && j >= 0) {
if(chessboard[i][j] == 'Q') {
return false;
}
i--;
j--;
}
//右上
i = rowIndex-1;
j = columnIndex+1;
while(i >= 0 && j < chessboard.length) {
if(chessboard[i][j] == 'Q') {
return false;
}
i--;
j++;
}
return true;
}
public static void main(String[] args) {
}
}