n皇后问题
题目描述
对于四皇后问题的解:
放置一个皇后,棋盘被占据的解为:
很明显,每行只能放置,且只能放置一个皇后。。
(代码中 queen(row + 1)来实现的)
一个完整的示例:
放第一个皇后
放第二个皇后
放第三个皇后
放第四个皇后
在放置过程中,如果一行中没有位置放了,就回溯到上一行。
代码中是递归调用queen(当前行+1),遍历所有列,如果没有合适的,就执行完当前的方法了,当前queen方法出栈,回溯到上一层的方法queen(当前行),列+1,继续判断位置是否合理。。。。
//遍历当前行的列
for (int col = 0; col < N; col++) {
if (!isDangerous(row, col)){
//每次放置皇后的时候 都先对该行进行清空
for (int c = 0; c < N; c++) {
arr[row][c] = 0;
}
arr[row][col] = 1;
queen(row + 1);
}
}
某次尝试错误,回溯到之前的状态,重新尝试:回溯法。
参考资料
- 我们从第一行开始遍历放入棋盘判断上、右上、左上是否有棋子(向下无需遍历,我们从上向下遍历)
- 若在遍历过程中一整行都没有可放入的格子则返回上一列继续向后遍历直至每一行都有正确格子
JAVA实现
private static int count = 0;//记录解的个数
private static final int N = 4;//N皇后 矩阵的尺寸
private static int[][] arr = new int[N][N];//棋盘数据 我们在二维数组中用1代表棋子 0代表可放入
//递归的解决row角标行 皇后的问题 如果row==N 说明一个解就出来了
private static void queen(int row) {
if (row == N){//当行遍历到N皇后尺寸最大值时返回答案
count++;
System.out.println("第" + count + "个解:");
printArr();
}else {
//遍历当前行的列
for (int col = 0; col < N; col++) {
if (!isDangerous(row, col)){
//每次放置皇后的时候 都先对该行进行清空
for (int c = 0; c < N; c++) {
arr[row][c] = 0;
}
arr[row][col] = 1;
queen(row + 1);
}
}
}
}
//判断上、左上、右上是否有格子
private static boolean isDangerous(int row, int col) {
//向上
for (int r = row - 1; r >= 0; r--) {
if (arr[r][col] == 1){
return true;
}
}
//左上
for (int r = row - 1, c = col - 1; r >= 0 && c >= 0 ; r--,c--) {
if (arr[r][c] == 1){
return true;
}
}
//右上
for (int r = row - 1, c = col + 1; r >= 0 && c < N ; r--,c++) {
if (arr[r][c] == 1){
return true;
}
}
return false;
}
private static void printArr() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
递归实现回溯
测试方法:
public static void main(String[] args) {
queen(0);//一行一行解决问题
}
参考资料
力扣提交代码
class Solution {
private static int count = 0;//记录解的个数
//private static final int N = n;//N皇后 矩阵的尺寸
//private static int[][] arr = new int[n][n];//棋盘数据 我们在二维数组中用1代表棋子 0代表可放入
private static int total = 0;
//递归的解决row角标行 皇后的问题 如果row==N 说明一个解就出来了
private static void queen(int row,int[][] arr,int n) {
if (row == n){//当行遍历到N皇后尺寸最大值时返回答案
count++;
System.out.println("第" + count + "个解:");
total++;
//printArr();
}else {
//遍历当前行的列
for (int col = 0; col < n; col++) {
if (!isDangerous(row, col,arr,n)){
//每次放置皇后的时候 都先对该行进行清空
for (int c = 0; c < n; c++) {
arr[row][c] = 0;
}
arr[row][col] = 1;
queen(row + 1,arr,n);
}
}
}
}
//判断上、左上、右上是否有格子
private static boolean isDangerous(int row, int col,int[][] arr,int n) {
//向上
for (int r = row - 1; r >= 0; r--) {
if (arr[r][col] == 1){
return true;
}
}
//左上
for (int r = row - 1, c = col - 1; r >= 0 && c >= 0 ; r--,c--) {
if (arr[r][c] == 1){
return true;
}
}
//右上
for (int r = row - 1, c = col + 1; r >= 0 && c < n ; r--,c++) {
if (arr[r][c] == 1){
return true;
}
}
return false;
}
// private static void printArr() {
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < N; j++) {
// System.out.print(arr[i][j] + " ");
// }
// System.out.println();
// }
// }
public static int totalNQueens(int n) {
int[][] arr = new int[n][n];
count=0;
queen(0,arr,n);
return count;
}
}