題目描述:
LeetCode題目51. N皇后
n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,並且使皇后彼此之間不能相互攻擊。
上圖爲 8 皇后問題的一種解法。
給定一個整數 n,返回所有不同的 n 皇后問題的解決方案。
每一種解法包含一個明確的 n 皇后問題的棋子放置方案,該方案中 ‘Q’ 和 ‘.’ 分別代表了皇后和空位。
示例1
輸入: 4
輸出: [
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],
["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解釋: 4 皇后問題存在兩個不同的解法。
思路分析:
約束條件爲每個棋子所在的行、列、對角線都不能有另一個棋子。
使用一維數組表示一種解法,下標(index)表示行,值(value)表示該行的Q(皇后)在哪一列。
每行只存儲一個元素,然後遞歸到下一行,這樣就不用判斷行了,只需要判斷列和對角線。
當result[row] = column時,即row行的棋子在column列。
對於[0, row-1]的任意一行(i 行),若 row 行的棋子和 i 行的棋子在同一列,則有result[i] == column;
若 row 行的棋子和 i 行的棋子在同一對角線,等腰直角三角形兩直角邊相等,即 row - i == Math.abs(result[i] - column)
布爾類型變量 isValid 的作用是剪枝,減少不必要的遞歸。
解法:
import java.util.LinkedList;
import java.util.List;
public class NQueens {
public static void main(String[] args) {
NQueens queen=new NQueens();
List<List<String>> myList=queen.solveNQueens(4);
System.out.println(myList);
}
public List<List<String>> solveNQueens(int n) {
int[] result=new int[n];
List<List<String>> resultList=new LinkedList<>();
dfs(resultList,result,0,n);
return resultList;
}
public void dfs(List<List<String>> resultList,int[] result,int row,int n) {
//核心函數,回溯法的思想
for(int column=0;column<n;column++) {
boolean isVaild=true;
result[row]=column;
//用於判斷皇后當前皇后是否可以放在此位置
for(int i=row-1;i>=0;i--) {
if(result[i]==column||row-i==Math.abs(result[i]-column)) {
isVaild=false;
break;
}
}
if(isVaild) {
//遞歸終止條件,如果全部擺好,則輸出所有皇后的座標
if(row==n-1) {
List<String> list=new LinkedList<>();
for(int x=0;x<n;x++) {
StringBuilder sb=new StringBuilder();
for(int y=0;y<n;y++) {
sb.append(result[x]==y?"Q":".");
}
list.add(sb.toString());
}
resultList.add(list);
return;
}else {
dfs(resultList,result,row+1,n);
}
}
}
}
}
運行結果: