力扣:51. N皇后

力扣:51. N皇后

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens

1、思路

暴力求解,回溯剪枝。

穷举每一种情况,从第1行到第n行,每一行选择一列往下穷举,当每一行都有皇后的时候,判断该解决方案是否符合要求。若满足要求,则放入结果集,否则,抛弃。

剪枝:

该题剪枝可以大大提高时间复杂度,因为大部分的摆放方案是不对的。

首先用一个判断摆放是否合理的函数,该函数主要原理为,放置皇后从第1行往第n行进行,每次放置第i行第j列的时候判断在该行左、右上角45度方向,垂直方向有没有皇后,若有的话就不能放,就返回false,否则,返回true。

代码如下:

 bool isValid(int row,int col,int n,vector<string>&board){
        for(int i=0;i<row;i++){
            if(board[i][col]=='Q')return false;
        }
        for(int i = row-1,j=col-1;i>=0&&j>=0;i--,j--){
            if(board[i][j]=='Q')return false;
        }
        for(int i = row-1,j=col+1;i>=0&&j<n;i--,j++){
            if(board[i][j]=='Q')return false;
        }
        return true;
    }

回溯代码如下:

  void bt(int k,int n,vector<string>& board){
        if(k==n){
            res.push_back(board);
            return;
        }
        for(int i = 0;i<n;i++){
            if(isValid(k,i,n,board)){
                board[k][i]='Q';
                bt(k+1,n,board);
                board[k][i]='.';
            }//若该位置不合理,则在该行的下一列进行尝试放置。
        }
    }

完整代码如下:

class Solution {
public:
    vector<string>board;
    vector<vector<string>> res;
    void bt(int k,int n,vector<string>& board){
        if(k==n){
            res.push_back(board);
            return;
        }
        for(int i = 0;i<n;i++){
            if(isValid(k,i,n,board)){
                board[k][i]='Q';
                bt(k+1,n,board);
                board[k][i]='.';
            }
        }
    }
    bool isValid(int row,int col,int n,vector<string>&board){
        for(int i=0;i<row;i++){
            if(board[i][col]=='Q')return false;
        }
        for(int i = row-1,j=col-1;i>=0&&j>=0;i--,j--){
            if(board[i][j]=='Q')return false;
        }
        for(int i = row-1,j=col+1;i>=0&&j<n;i--,j++){
            if(board[i][j]=='Q')return false;
        }
        return true;
    }

    vector<vector<string>> solveNQueens(int n) {
        board.resize(n,string(n,'.'));
        bt(0,n,board);
        return res;
    }
};

执行用时:4 ms, 在所有 C++ 提交中击败了90.52%的用户

内存消耗:7.2 MB, 在所有 C++ 提交中击败了60.52%的用户

通过测试用例:9 / 9

其他:

这里还有一个代码是几个月之前写的,由于没有注释,不太能看的懂以前的思路了。

执行用时: 8 ms
内存消耗: 7.7 MB
提交时间:3 个月前

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<int> path;
        backtrack(res,path,0,n);
        return res;
    }
    void backtrack(vector<vector<string>>&res,vector<int>&path,int m,int n){
        if(m==n){
            vector<string> tmpR;
            for(int i =0;i<path.size();i++){
                string tmp="";
                tmp.insert(0,path[i],'.');
                tmp.insert(path[i],1,'Q');
                tmp.insert(path[i]+1,n-path[i]-1,'.');
                tmpR.push_back(tmp);
            }
            res.push_back(tmpR);
        }
        for(int i=0;i<n;i++){
            int flag=0;
            for(int j = 0;j<path.size();j++){
                if(i==path[j]||abs(path[j]-i)==m-j){
                    flag=1;
                    break;
                }
            }
            if(flag==1){
                continue;
            }
            path.push_back(i);
            backtrack(res,path,m+1,n);
            path.pop_back();
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值