- 代码比较少,几乎一比一的注释,可以多看两遍,debug试试。
- 如果你看懂了,就给我点个赞吧,万分感谢!(统计下有多少人看懂了)
public class Solution0812 {
public static void main(String[] args) {
Solution0812 solution = new Solution0812();
solution.eightQueen(8);
}
private int count = 0;
private void eightQueen(int n) {
//初始化,所有的格子填充一个点
char[][] queen = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
queen[i][j] = '.';
}
}
//从第0行开始安排 Queen 的摆放位置
backtrack(queen, 0, n);
}
private void backtrack(char[][] queen, int i, int n) {
if (i == n) {
//已经进行到第n行,则表示满足规则,棋盘已经列举完毕,进行棋盘打印,并返回
count++;
System.out.println("第" + count + " 种可能: " + Arrays.deepToString(queen));
return;
}
//j是列数,表示预计在【i,j】放上下一个 Queen
for (int j = 0; j < n; j++) {
//判断在【i,j】放一个 Queen ,是否有效可行,如果不可行,则 j++,换下一列试试
if (!judge(queen, i, j)) continue;
//如果可行,则在【i,j】处放一个 Queen
queen[i][j] = 'Q';
//继续进行下一行 Queen 的位置摆放,因为在这一行肯定只能放一个 Queue
backtrack(queen, i + 1, n);
//如果棋盘全部摆放结束,或者尝试在第【i + 1,j】,j 从0-n (前闭后开)摆放Queue,都不可行
//则需要进行回溯,即第i行的 Queen 需要换一个位置摆放
//回溯,将【i,j】的Queen还原为'.',遍历尝试在【i,j+1】位置摆放一个Queen
//回溯的本质是枚举所有可能情况(并进行适当剪枝,去掉不可能的路径,返回上一步,继续枚举)
queen[i][j] = '.';
}
}
/**
* 判断在【i,j】放一个queen,是否有效可行
*/
private boolean judge(char[][] queen, int i, int j) {
//在 i 这一行只能放一个 Queen ,之前已经做过处理
//在 j 这一列只能放一个 Queen ,如果检测到这一列有 Queen ,则不可行,返回false
for (int k = 0; k < i; k++) {
if (queen[k][j] == 'Q')
return false;
}
//比较斜对角
//往左上角方向延伸,如果检测到这一条对角线有 Queen ,则不可行,返回false
for (int z = i - 1, k = j - 1; z >= 0 && k >= 0; z--, k--) {
if (queen[z][k] == 'Q') return false;
}
//往右上角方向延伸,如果检测到这一条对角线有 Queen ,则不可行,返回false
for (int z = i - 1, k = j + 1; z >=0 && k < queen.length; z--, k++) {
if (queen[z][k] == 'Q') return false;
}
//行、列、对角线都匹配完成,返回true,表示【i,j】处可以放置一 个Queen
return true;
}
}
输出结果:
总共92种解法