数据结构---n皇后问题


在这里插入图片描述

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);
                }
            }

在这里插入图片描述
在这里插入图片描述

某次尝试错误,回溯到之前的状态,重新尝试:回溯法

参考资料

  1. 我们从第一行开始遍历放入棋盘判断上、右上、左上是否有棋子(向下无需遍历,我们从上向下遍历
  2. 若在遍历过程中一整行都没有可放入的格子则返回上一列继续向后遍历直至每一行都有正确格子

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;
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值