【问题描述】在n×n的方格棋盘上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。如下图所示是6皇后问题的一个解。
q[1…6]={2,4,6,1,3,5}
对于(i,j)位置上的皇后,是否与已放好的皇后(k,q[k])(1≤k≤i-1)有冲突呢?
设queen(i,n)是在1~i-1行上已经放好了i-1个皇后,用于在i~n行放置n-i+1个皇后,则queen(i+1,n)表示在1~i行上已经放好了i个皇后,用于在i+1~n行放置n-i个皇后。
queen(i+1,n)比queen(i,n)少放置一个皇后。所以queen(i+1,n)是“小问题”,queen(i,n)是“大问题”。
bool place(int i,int j) //测试(i,j)位置能否摆放皇后
{ if (i==1) return true; //第一个皇后总是可以放置
int k=1;
while (k<i) //k=1~i-1是已放置了皇后的行
{ if ((q[k]==j) || (abs(q[k]-j)==abs(i-k)))
return false;
k++;
}
return true;
}
void queen(int i,int n) //放置1~i的皇后
{ if (i>n)
dispasolution(n); //所有皇后放置结束
else
{ for (int j=1;j<=n;j++) //在第i行上试探每一个列j
if (place(i,j)) //在第i行上找到一个合适位置(i,j)
{ q[i]=j;
queen(i+1,n);
}
}
}
class Solution {
int[] q;
List<List<String>> result;
public List<List<String>> solveNQueens(int n) {
q = new int[n + 1];
result=new ArrayList<>();
queen(1,n);
return result;
}
//测试(i,j)位置能否放皇后
boolean place(int i, int j) {
//第一个位置OK
if (i == 1) {
return true;
}
int k = 1;
while (k < i) {
if (j == q[k] || Math.abs(i - k) == Math.abs(j - q[k])) {
return false;
}
k++;
}
return true;
}
void queen(int i, int n) {
if (i > n) {
dispasolution(n); //得到一个解
return;
}
for (int j = 1; j <= n; j++) {
if (place(i, j)) {
q[i]=j;
queen(i + 1, n);
}
}
}
private void dispasolution(int n) {
List<String> list = new ArrayList<>();
for (int i = 1; i <= n; i++) {
StringBuilder builder = new StringBuilder();
for (int j = 1; j <= n; j++) {
if (j == q[i]) {
builder.append("Q");
} else {
builder.append(".");
}
}
list.add(builder.toString());
}
result.add(list);
}
}