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;
}
相关推荐
lisw0513 分钟前
发酵算法两大应用方向解析
算法·数学建模
BioRunYiXue17 分钟前
使用docker分析高通量测序数据
java·数据库·人工智能·spring cloud·docker·tomcat·html
Shaoshing1 小时前
缓存一致问题及常见解决方案
java·缓存
动词ing1 小时前
【题目练习】全排列
算法
聚美智数1 小时前
文档转换 API‑文档转 PDF‑PDF 转文档‑异步文档处理‑文件格式迁移‑转换结果回调推送 API 接口介绍
android·java·pdf
从零数据分析1 小时前
零基础学SQL 23:和上月比总对不上?LAG/LEAD 一步取出上一次(附 4 个模板)
java·数据库·sql·mysql·oracle·sqlite·database
yuzhiboyouye1 小时前
com.fasterxml.jackson.annotation 里最常用高频的注解,可以按“控制字段、控制格式、控制结构、控制流程”来记
java·开发语言
苜蓿muxu1 小时前
简述 ConcurrentHashMap 和 CopyOnWriteArrayList 的区别以及各自适用场景
java·编程语言
易小尊1 小时前
Dixon-Coles 的 τ 函数,我写错了三次
算法
9527!到!2 小时前
Springboot @value读取配置参数踩坑&推荐解决方案
java·spring boot·spring