(col x-y x+y 利用了数学斜线方程的x,y关系)(法二:位运算) n皇后问题 Leetcode81

本文介绍了三种解法来解决N皇后问题,包括经典的回溯法和位运算解法。N皇后问题要求在N×N的棋盘上放置N个皇后,使得任意两个皇后不在同一行、同一列或同一斜线上。文章提供了详细的代码实现,并针对简单情况(只需返回布局数量)进行了优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路

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

题目

任意两个皇后不能在同一列, 也不能在正斜对角线 和 负斜对角线上
在这里插入图片描述
在这里插入图片描述

代码及注释

class Solution {


    List<List<String>> res ;
    Set<Integer> col;
    Set<Integer> xy_sub;
    Set<Integer> xy_sum;
    public List<List<String>> solveNQueens(int n) {
         res = new LinkedList<>();

        col = new HashSet<>();
       xy_sub = new HashSet<>();
       xy_sum = new HashSet<>();

         int[] path = new int[n];
        Arrays.fill(path,-1);
        dfs(n,path,0);
        return res;



    }


    public void dfs(int n , int[] path,int row){
        if(row == n){
          List<String> board =   Generat_List(path,n);
          res.add(board);
          return;
        }

        for(int i =0; i<n; i++){
            if(!col.contains(i) && !xy_sub.contains(row - i) & !xy_sum.contains(row + i)){
                path[row] = i;
                col.add(i);         // 你怎么忘记标记 “列” 了呢?
                xy_sub.add(row - i);
                xy_sum.add(row + i);
                dfs(n, path,row +1);

                path[row] = -1;  // 撤销影响
                col.remove(i);   // 不止工作数组要撤销影响,最主要的是标记数组要撤销影响啊
                xy_sub.remove(row - i);
                xy_sum.remove(row + i);
            }
        }
        
    }

    public List<String> Generat_List(int[] path,int n){
        List<String> board = new LinkedList<>();
        
        for(int p : path){
            char[] row = new char[n];
            Arrays.fill(row,'.');
            row[p] = 'Q';
            board.add(new String(row));
        }

        return board;
    }

}

n皇后问题II(简单,只需返回 有多少种布局)

class Solution {
    
    Set<Integer> col;
    Set<Integer> xy_sub;
    Set<Integer> xy_sum;
    int res_Sum = 0;
    public int  totalNQueens(int n) {
        col = new HashSet<>();
       xy_sub = new HashSet<>();
       xy_sum = new HashSet<>();



        dfs(n,0);
        return res_Sum;



    }


    public void dfs(int n ,int row){
        if(row == n){
            res_Sum++;
          return;
        }

        for(int i =0; i<n; i++){
            if(!col.contains(i) && !xy_sub.contains(row - i) & !xy_sum.contains(row + i)){
                col.add(i);         // 你怎么忘记标记 “列” 了呢?
                xy_sub.add(row - i);
                xy_sum.add(row + i);
                dfs(n, row +1);


                col.remove(i);   // 工作数组要撤销影响,最主要的是标记数组要撤销影响啊
                xy_sub.remove(row - i);
                xy_sum.remove(row + i);
            }
        }
        
    }


}

位运算解法(返回 有多少种不同的布局)

class Solution {

    int res_Sum = 0;
    public int  totalNQueens(int n) {
        int col = 0;
        int pie = 0;
        int na  = 0; // 初始时,从第0 行开始分配棋子, 此时棋盘上没有棋子,所以没有不能下的col、pie(左斜线)、(右斜线),所以 col等为0(其实参与运算时的形式是col=0000)
        dfs(n,0,col,pie,na);

        return res_Sum;

    }


    public void dfs(int n, int row, int col, int pie, int na){
        
        // 把所有 列 和 斜线 的位置都“或” 之后,再取反,这些位置就变成了0了,再与 n个1 “1111” 做“与运算”, 就可以的到当前能下的位置
       int  remain = ~(col | pie | na) & ((1 << n) - 1);

        if(row == n){
            res_Sum++;
            return;
        }

        while(remain != 0){

            int choice = remain & (-remain);    // 这里只是 每次都选最后面的一个没下过的
            remain = remain & (remain - 1);
            dfs(n,row+1, col | choice,  (pie | choice) << 1,  (na | choice) >> 1);
            // 这里不用撤销, 因为工作数组的变化都是在dfs函数参数列表里变化的
        }

    }


}
// @solution-sync:end

class Main {

    public static void main(String[] args) {
        int n = 4;

        int result = new Solution().totalNQueens(n);
        System.out.println(result);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雄狮少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值