N-Queens -- 回溯法 -- 力扣101算法题解笔记

6.3N-Queens -- 回溯法

题目描述

先说一下,这个题目十分之困难。

给定一个大小为n的正方形国际象棋棋盘,求有多少种方式可以放置n个皇后,并使得她们互不攻击,即每一行、列、左斜、右斜最多只有一个皇后

输入输出样例

Input :4

Output: \[".Q..", "...Q","Q...","..Q.", // Solution 1

"..Q.", "Q...","...Q",".Q.."] // Solution 2

注:.表示空白位置,Q代表皇后

题解

类似于在矩阵中寻找字符串,本体也是通过修改状态矩阵来进行回溯操作,不同的是,我们需要对每一行列,左斜右斜,建立访问数组,来记录他们是否存在皇后。

注意,本题有一个隐藏条件,是满足条件的结果中每一行或列有且仅有一个皇后。这是因为我们一共只有n行n列。所以,如果我们通过对每一行遍历来插入皇后,我们就不需要对行建立访问数组了。

这个是缓解这题难度的关键

cpp 复制代码
#include <vector>
#include <iostream>
using namespace std;

void backtracking(vector<vector<string>>& ans, vector<string>& board, 
    vector<bool> &column, vector<bool> &ldiag, vector<bool> &rdiag, int row, int n) {
    if (row == n) {
        ans.push_back(board);
        return;
    }
    for (int i = 0; i < n; ++i) {
        if (column[i] || ldiag[n - row + i - 1] || rdiag[row + i + 1]) {
            continue;
        }
        //修改当前节点状态
        board[row][i] = 'Q';
        column[i] = ldiag[n - row + i - 1] = rdiag[row + i + 1] = true;
        //递归子节点
        backtracking(ans, board, column, ldiag, rdiag, row + 1, n);
        //回改当前节点状态
        board[row][i] = '.';
        column[i] = ldiag[n - row + i - 1] = rdiag[row + i + 1] = false;
    }
}

vector<vector<string>> solveNQueens(int n) {
    vector<vector<string>> ans;
    if (n == 0) {
        return ans;
    }
    vector<string> board(n, string(n, '.'));
    vector<bool> column(n, false), ldiag(2 * n - 1, false), rdiag(2 * n - 1, false);
    backtracking(ans, board, column, ldiag, rdiag, 0, n);
    return ans;
}

int main() {
    int n = 4;
    vector<vector<string>> res = solveNQueens(n);
    for (int i = 0; i < res.size(); ++i) {
        cout << "[";
        for (int j = 0; j < res[i].size(); ++j) {
            cout << "   \"" << res[i][j] << "\"";
            if (j != res[i].size() - 1) {
                cout << ",";
            }
            cout << endl;
        }
        if (i != res.size() - 1) {
            cout << "  ]," << endl;
        }
        else {
            cout << "  ]" << endl;
        }
        cout << "  // Solution " << i + 1 << endl;
    }
    cout << "]" << endl;
    return 0;
}
相关推荐
小bo波3 小时前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
nanxun8861 天前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103511 天前
Day01 | Java 基础(Java SE)
java
行者全栈架构师1 天前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师1 天前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_01 天前
mac(m5)平台编译openjdk
java
JieE2122 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack202 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树2 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色