N皇后问题

N皇后问题-I

问题描述

n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。
给定一个整数n,返回所有不同的n皇后问题的解决方案。
每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。

样例:
对于4皇后问题存在两种解决的方案:

[

    [".Q..", // Solution 1

     "...Q",

     "Q...",

     "..Q."],

    ["..Q.", // Solution 2

     "Q...",

     "...Q",

     ".Q.."]

]

算法思路

基本的思路就是全排列的DFS问题,也可以说是回溯问题。大家可以不区分这两个概念,认为回溯和DFS是一样的问题。

这道题让求出所有的方案,基本上求所有方案的问题,没有什么别的做法,就是枚举,暴力搜索。那么枚举的话,90%都是用DFS来做。那你可能要问了,怎么转换成DFS问题那。

其实是有一个模板的(针对全排列的DFS的模板):

vector<vector<int>> permute(vector<int> &nums) {
        vector<vector<int>> results;

        // 不用排序

        dfs(nums, vector<bool>(nums.size(), false), vector<int>(), results);

        return results;
    }

    // 1. 定义:找到所有permutation开头的排列,加到results中。比如所有以1开头的排列,或所有以空开头的排列
    void dfs(vector<int> nums, vector<bool> visited, vector<int> permutation, vector<vector<int>> & results) {

        // 2. 递归的出口
        if (permutation.size() == nums.size()) {
            results.push_back(permutation);
            return;
        }

        // 3. 递归的拆解
        for (int i = 0; i < nums.size(); ++i) {
            if (visited[i]) {
                continue;
            }

            permutation.push_back(nums[i]);
            visited[i] = true;

            dfs(nums, visited, permutation, results);

            visited[i] = false;
            permutation.pop_back();
        }
    }

对于这个模板,还请个位理解记忆并背诵。然后再这个基础上我们尝试DFS来搜索所有的可能放置方案,对于有效的方案记录下来,无效的方案直接跳过,完整AC代码:

class Solution {
public:
    /*
     * @param n: The number of queens
     * @return: All distinct solutions
     */
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<int>> results;

        dfs(n, vector<int>(), results);

        vector<vector<string>> ret(results.size(), vector<string>(n,string(n,'.')));
        // 构造ret, results中放置的是第i行皇后,应该放置的位置[0,n-1]
        for (int i = 0; i < results.size(); ++i) {
            vector<int> queuens = results[i];

            for (int j = 0; j < queuens.size(); ++j) {
                ret[i][j][queuens[j]] = 'Q';
            }
        }

        return ret;
    }

    void dfs(int n, vector<int> permutation, vector<vector<int>> &results) {
        if (permutation.size() == n) {
            results.push_back(permutation);
            return;
        }

        for (int i = 0; i < n; ++i) {
            if (!isValid(permutation, i)) {
                continue;
            }

            permutation.push_back(i);
            dfs(n, permutation, results);
            permutation.pop_back();
        }
    }

    bool isValid(vector<int> cols, int chosenCol) {
        int rows = cols.size();
        for (int i = 0; i < cols.size(); ++i) {
            int col = cols[i];

            // 同一列
            if (chosenCol == col) {
                return false;
            }

            // 同一斜线
            if (i - rows == col - chosenCol) { // 左斜向下
                return false;
            }

            if (i - rows == chosenCol - col) { // 右斜向上
                return false;
            }
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值