• b_lc_N皇后(一列一列地放,放完就检查)


    构造n皇后

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

    上图为 8 皇后问题的一种解法。
    给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
    每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

    输入:4
    输出:[
     [".Q..",  // 解法 1
      "...Q",
      "Q...",
      "..Q."],
    
     ["..Q.",  // 解法 2
      "Q...",
      "...Q",
      ".Q.."]
    ]
    解释: 4 皇后问题存在两个不同的解法。
    

    思路
    回溯放置皇后 'Q' 和棋子 '.',放完整个棋盘后就对于每一种放置方案都检查是否合法,这是最朴素的做法;
    剪枝:每放完一列就去检查当前方法是否合法(这里为了方便选择每次放完一列)

    const int N=100;
    class Solution {
    public:
        int n; char g[N][N];
        vector<vector<string>> ans;
        bool chk(int x, int y) {
            for (int i=x-1; i>=0; i--) {
                int d=x-i;
                if (g[i][y]=='Q' || (y-d>=0 && g[i][y-d]=='Q') || (y+d<n && g[i][y+d]=='Q'))
                    return false;
            }
            return true;
        }
        void dfs(int i) {
            if (i==n) {
                vector<string> now;
                for (int i=0; i<n; i++) {
                    string s;
                    for (int j=0; j<n; j++)
                        s+=g[i][j];
                    now.push_back(s);
                }
                ans.push_back(now);
                return;
            }
            for (int j=0; j<n; j++) if (chk(i, j)) {
                g[i][j]='Q';
                dfs(i+1);
                g[i][j]='.';
            }
        }
        vector<vector<string>> solveNQueens(int n) {
            this->n=n;
            memset(g,'.',sizeof g);
            dfs(0);
            return ans;
        }
    };
    

    复杂度分析

    • Time\(O(2^n)\)
    • Space\(O(...)\)

    题外话:

    • 主对角线特点:所有格子格子的行下标与列下标之相同
    • 辅对角线特点:所有格子格子的行下标与列下标之相等

    合法的序列

    Q1,Q2,…,QN 来表示一种棋盘摆放,其中 Qi 表示第 i 列的皇后所在的行号。

    疑惑
    不知道为什么用一个map来记录两条对角线为什么不行(加了10w的偏置值也不行)

    #include<bits/stdc++.h>
    using namespace std;
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int q; cin>>q;
        for (int i=0; i<q; i++) {
            int m,valid=1; 
            cin>>m;
            unordered_map<int, bool> mx, my, md1, md2;
            for (int y=1; y<=m; y++) {
                int x; cin>>x;
                if (mx[x] || my[y] || md1[x+y] || md2[x-y]) {
                    valid=0;
                }
                mx[x]=my[y]=md1[x+y]=md2[x-y]=1;
            }
            cout<<(valid ? "YES" : "NO")<<'\n';
        }
        return 0;
    }
    

    N皇后II

    给定一个棋盘大小n,返回n皇后不同的解决方案的数量。

    思路:记录每一行放下的皇后的位置

    class Solution:
        ans=0
        def totalNQueens(self, n: int) -> int:
            def valid(x,row):
                for c in range(x):
                    if row[c]==row[x] or abs(x-c)==abs(row[x]-row[c]):
                        return False
                return True
            def dfs(x,row):
                if x==n:
                    self.ans+=1
                    return
                for y in range(n):
                    row[x]=y
                    if valid(x,row):
                        dfs(x+1,row)
            row=[0]*n
            dfs(0,row)
            return self.ans
    
  • 相关阅读:
    【读书笔记】组合计数中的行列式方法 基础
    【读书笔记】有序分拆和无序分拆的结论速览
    三种常见的卷积概述(线性卷积周期卷积圆周卷积)以及重叠保留法重叠相加法
    大会COOKIE与session
    JVM监测&工具[整理中](五)
    谷歌浏览器启动参数
    Maven的配置文件pom.xml
    classLoader卸载与jvm热部署
    在Windows Server 2008R2中安装配置SMTP服务
    Could not start the MS DTC Transaction Manager
  • 原文地址:https://www.cnblogs.com/wdt1/p/13606752.html
Copyright © 2020-2023  润新知