题目:N皇后 middle
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。
当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一到七步,可进可退。
思路:
其实和全排列一样,只是输出麻烦了点,不是将每个列的位置集合直接输出,
而是要输出整个棋盘字符串,所以在加入集合时应该改造下
package leetCode.DFS;
import java.util.ArrayList;
import java.util.List;
public class lc_dfs_51_solveNQueens {
public static void main(String[] args) {
lc_dfs_51_solveNQueens m = new lc_dfs_51_solveNQueens();
m.solveNQueens(6);
}
public List<List<String>> solveNQueens(int n) {
List<List<String>> ans = new ArrayList<>();
if (n <= 0)
return ans;
boolean[] IscolumnPlaced = new boolean[n];
boolean[] rightTilt = new boolean[2 * n];//为什么是2n-1个,为啥写2n
boolean[] leftTilt = new boolean[2 * n];
dfs(0, n, new ArrayList<Integer>(), ans, IscolumnPlaced, rightTilt, leftTilt);
/*
输出看看结果
for (List list : ans) {
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
System.out.println("-----------");
}*/
return ans;
}
/**
* @param row 第几行,从0开始
* @param n n个皇后
* @param place 放置皇后列的位置,共n个数,第i个数num代表i行的第num列,i从0开始
* @param ans 最后的结果
* @param IscolumnPlaced 该列是否被放置
* @param rightTilt 右斜对角,共2*n-1个右斜对角,记录是否被放置,每个右斜对角row-col是常数
* @param leftTilt 左斜对角,共2*n-1个左斜对角,每个左斜对角row+col是常数
*/
public void dfs(int row, int n, List<Integer> place, List<List<String>> ans,
boolean[] IscolumnPlaced, boolean[] rightTilt, boolean[] leftTilt) {
if (row >= n) {
//原本只需要简单地将位置集合place放入ans中,但题目要求变成字符串输出,所以要转化成字符串
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < place.size(); i++) {
String s = "";
for (int j = 0; j < n; j++) {
if (j == place.get(i))//皇后的列输出"Q"
s += "Q";
else//其余输出"."
s += ".";
}
list.add(s);//将一行的结果放入list中,共n行
}
ans.add(list);//一个完整的结果放入ans中
}
for (int col = 0; col < n; col++) {
// 行不用判断重复,因为每次都递增一行,row+1,所以不会重复
if (!IscolumnPlaced[col] && !rightTilt[row - col + n] && !leftTilt[row + col]) {
place.add(col);//放置的是皇后在row行的col列
IscolumnPlaced[col] = true;
// 右斜对角的范围从-(n-1)~(n-1),将其+n,防止溢出全部变为正数,变成1~(2n-1),所以rightTilt[2*n]
rightTilt[row - col + n] = true;
// 左斜对角没有负数不会溢出,直接相加,最大为2(n-1),为了统一大小也写为2n
leftTilt[row + col] = true;
dfs(row + 1, n, place, ans, IscolumnPlaced, rightTilt, leftTilt);
//该位置试完后记得弹出并将访问过的位置置为没访问
place.remove(place.size() - 1);
IscolumnPlaced[col] = false;
rightTilt[row - col + n] = false;
leftTilt[row + col] = false;
}
}
}
}