The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space respectively.
非常典型的回溯问题,需要注意的点:
1、剪枝(确定性优化:不需要的就砍掉);
2、A*(不确定性优化:改变搜索顺序,不改变搜索的结果,不一定更优);
3、DFS限制搜索长度,探测长度寻找最优解—>判定问题.
//记录每列走第几行
public static int[] path= new int[100];
public static List<List<String>> res = new ArrayList<>();
//记录历史上走过的行
public static boolean[] row = new boolean[100];
//辅助判断对角线是否被走过,例如 x+y=k,记录所有已走的 x+y的和,不能有两个点该和相同,例如 colIdx +
public static boolean[] diagonal = new boolean[100];
//辅助判断反对角线是否被走过,例如 y = x + colIdx - i, 记录所有已走的 x + colIdx = y + i 的点的值,
//例如 colIdx - i + n -1 为避免负数
public static boolean[] reverse = new boolean[100];
public List<List<String>> solveNQueens(int n) {
res.clear();
dfs(0,n);
return res;
}
public void dfs(int colIdx, int n){
if(colIdx >= n){
//根据 path 信息记录该组结果,之后返回好进行其它结果的回溯探测
List<String> chess = new ArrayList<String>();
for(int i = 0 ;i < n; i++) {
String tmpRow = "";
for (int j = 0; j < n; j++) {
if (path[i] == j)
tmpRow += 'Q';
else tmpRow += '.';
}
chess.add(tmpRow);
}
res.add(chess);
return;
}
//对某一列而言,任意行都有可能走
for(int i = 0 ; i < n; i++){
if(!row[i] && !diagonal[colIdx + i] && !reverse[colIdx - i + n -1]){
path[colIdx] = i;
row[i] = true;
diagonal[colIdx + i] = true;
reverse[colIdx - i + n -1] = true;
dfs(colIdx+1,n);
row[i] = false;
diagonal[colIdx + i] = false;
reverse[colIdx - i + n -1] = false;
}
}
}