leetcode N-Queens/N-Queens II, backtracking, hdu 2553 count N-Queens, dfs ...

本文深入探讨了N皇后问题的解决策略,通过改进的回溯算法和深度优先搜索优化,实现高效的解决方案。分析了验证检查过程中的优化策略,包括额外的占用数组来提高效率,并提供了具体的实现代码,包括简化版和完整版解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. for the backtracking part, thanks to the video of stanford cs106b lecture 10 by Julie Zelenski for the nice explanation of recursion and backtracking, highly recommended.

  2. in hdu 2553 cout N-Queens solutions problem, dfs is used.
    // please ignore, below analysis is inaccurate, though for inspiration considerations, I decided to let it remain.
    and we use a extra occupied[] array to opimize the validation test, early termination when occupied[i]==1, and in function isSafe the test change from 3 to 2 comparisons.
    for the improvement, here is an analysis:
    noted that total call of dfs for n is less than factorial(n), for convenience we take as factorial(n),
    in this appoach, in pow(n,n)-factorial(n) cases, we conduct one comparison, and three for others
    otherwise, for all pow(n,n) cases, we must conduct three comparisons,
    blow is a list for n from 1 to 10,

   n        n!           n^n   n!/n^n
   1        1             1   1.00000
   2        2             4   0.50000
   3        6            27   0.22222
   4       24           256   0.09375
   5      120          3125   0.03840
   6      720         46656   0.01543
   7     5040        823543   0.00612
   8    40320      16777216   0.00240
   9   362880     387420489   0.00094
  10  3628800   10000000000   0.00036

the table shows that, for almost all of the cases of large n (n>=4), we reduce 3 to 1 comparison in doing validation check.

occupied[i] is initilized to 0, before dfs, mark.

occupied[val]=1;

after dfs, unmark,

occupied[val]=0;

where val is the value chosen.
inspirations from chapter 3 Decompositions of graphs
in Algorithms(算法概论), Sanjoy Dasgupta University of California, San Diego Christos Papadimitriou University of California at Berkeley Umesh Vazirani University of California at Berkeley.

// leetcode N-Queens(12ms)

class Solution {
    vector<vector<string>> ans;
    int N;
    //int numofsol;

    void AddTo_ans(string &conf) {
        vector<string> vecstrtmp;
        string strtmp(N,'.');
        for(auto ind: conf) {
            vecstrtmp.push_back(strtmp);
            vecstrtmp.back()[(size_t)ind-1]='Q';
        }
        ans.push_back(vector<string>());
        ans.back().swap(vecstrtmp);
    }
    void RecListNQueens(string soFar, string rest) {
        if(rest.empty()) {
            //++numofsol;
            AddTo_ans(soFar);
        }
        else {
            int i,j,len=soFar.size(), flag;
            for(i=0;i<rest.size();++i) {
                for(j=0;j<len;++j) {
                    flag=1;
                    if(soFar[j]-rest[i]==len-j || soFar[j]-rest[i]==j-len) {
                        flag=0; break;
                    }
                }
                if(flag) RecListNQueens(soFar+rest[i],rest.substr(0,i)+rest.substr(i+1));
            }
        }
    }
public:
    vector<vector<string>> solveNQueens(int n) {
        ans.clear();
        //numofsol=0;
        N=n;
        string str;
        for(int i=1;i<=n;++i) str.push_back(i);
        RecListNQueens("", str);
        return ans;
    }
};

// with a tiny modification,
// leetcode N-Queens II (8ms)

class Solution {
    //vector<vector<string>> ans;
    int N;
    int numofsol;

    /*void AddTo_ans(string &conf) {
        vector<string> vecstrtmp;
        string strtmp(N,'.');
        for(auto ind: conf) {
            vecstrtmp.push_back(strtmp);
            vecstrtmp.back()[(size_t)ind-1]='Q';
        }
        ans.push_back(vector<string>());
        ans.back().swap(vecstrtmp);
    }*/
    void RecListNQueens(string soFar, string rest) {
        if(rest.empty()) {
            ++numofsol;
            //AddTo_ans(soFar);
        }
        else {
            int i,j,len=soFar.size(), flag;
            for(i=0;i<rest.size();++i) {
                for(j=0;j<len;++j) {
                    flag=1;
                    if(soFar[j]-rest[i]==len-j || soFar[j]-rest[i]==j-len) {
                        flag=0; break;
                    }
                }
                if(flag) RecListNQueens(soFar+rest[i],rest.substr(0,i)+rest.substr(i+1));
            }
        }
    }
public:
    int totalNQueens(int n) {
        //ans.clear();
        numofsol=0;
        N=n;
        string str;
        for(int i=1;i<=n;++i) str.push_back(i);
        RecListNQueens("", str);
        return numofsol;
    }
};

// hdu 2553, 15ms

#include <cstdio>
#include <vector>
#include <algorithm>

class countNQueenSol {
    static const int MAXN=12;
    static int values[MAXN];
    static int occupied[MAXN];
    static std::vector<int> ans;
    static int cnt, rownum;

    static bool isSafe(int val, int row) {
        for(int i=0;i<row;++i) {
            if(val-values[i]==row-i || val-values[i]==i-row)
            return false;
        }
        return true;
    }
    static void dfs(int row) {
        if(row==rownum) ++cnt;
        for(int i=0;i<rownum;++i) {
            if(occupied[i]==0 && isSafe(i,row)) {
                values[row]=i;
                occupied[i]=1;
                dfs(row+1);
                occupied[i]=0;
            }
        }
    }
public:
    static int getMAXN() { return MAXN; }
    static int solve(int k) {
        if(k<=0 || k>=countNQueenSol::MAXN) return -1;
        if(ans[k]<0) {
            cnt=0;
            rownum=k;
            dfs(0);
            //if(k==0) cnt=0; // adjust anomaly when k==0
            ans[k]=cnt;
        }
        return ans[k];
    }
};
int countNQueenSol::values[countNQueenSol::MAXN]={0};
int countNQueenSol::occupied[countNQueenSol::MAXN]={0};
std::vector<int> countNQueenSol::ans(countNQueenSol::MAXN,-1);
int countNQueenSol::cnt, countNQueenSol::rownum;

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    int n;
    while(scanf("%d",&n)==1 && n>0) {
        printf("%d\n",countNQueenSol::solve(n));
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。// p.s. If in any way improment can be achieved, better performance or whatever, it will be well-appreciated to let me know, thanks in advance.

转载于:https://www.cnblogs.com/qeatzy/p/4716220.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值