N皇后问题

N皇后是很经典的回溯算法题,类似的题目还有 https://leetcode-cn.com/problems/sudoku-solver/ (解数独),回溯法的思路类似DFS,
解决一个回溯问题,实际上就是一个决策树的遍历过程。 这类问题要考虑以下几点
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
我认为,回溯法其实就是一种穷举,时间复杂度一般都很高,N皇后问题的回溯法复杂度已经达到了O(n!),我的代码如下

#include<iostream>
#include<vector>
using namespace std;

/*0表示可以放棋子 1表示进入攻击范围 2表示该位置有皇后*/
typedef vector<int> vi;
typedef vector<vi> v2d;
typedef vector<v2d> v3d;
typedef pair<int, int> P;

v3d result;

void mark(v2d& chessboard, int i, int j) {
    int n = chessboard.size();
    for (int k = 0; k < n; k++) {   //横纵标记
        chessboard[i][k] = 1;
        chessboard[k][j] = 1;
    }
    int t1 = i + 1;
    int t2 = j + 1;
    while (t1 < n && t2 < n) {
        chessboard[t1][t2] = 1;
        t1++;
        t2++;
    }
    t1 = i - 1;
    t2 = j - 1;
    while (t1 >=0 && t2 >= 0) {
        chessboard[t1][t2] = 1;
        t1--;
        t2--;
    }
    t1 = i - 1;
    t2 = j + 1;
    while (t1 >= 0 && t2 < n) {
        chessboard[t1][t2] = 1;
        t1--;
        t2++;
    }
    t1 = i + 1;
    t2 = j - 1;
    while (t1 < n && t2 >= 0) {
        chessboard[t1][t2] = 1;
        t1++;
        t2--;
    }
    chessboard[i][j] = 2;
}
 
void dfs(v2d chessboard, int n, int row) {
   /* cout << endl;
    for (auto td : chessboard) {
        for (auto t : td)  cout << t;
        cout << endl;
    }*/
    vi psblist;  //可以放皇后的点集,只存纵坐标
    if (chessboard.size() == 0) {   //新建棋盘
        for (int i = 0; i < n; i++) {
            vi t(n, 0);
            chessboard.push_back(t);
        }
        for (int i = 0; i < n; i++) {
            psblist.push_back(i); //新棋盘取第一行作为回溯点集
        }
    }
    else {
        for (int i = 0; i < n; i++) {
            if (chessboard[row][i] == 0) psblist.push_back(i);
        }
    }
    for (auto j: psblist) {
        v2d huishu = chessboard;
        mark(huishu, row, j);
        if (row == n - 1) {
            result.push_back(huishu);   return;
        }
        else {
            dfs(huishu, n, row + 1);
        }
    }
}

vector<vector<string>> solveNQueens(int n) {
    if (n == 0)    return {};
    v2d chessboard;
    dfs(chessboard, n, 0);
    vector<vector<string>> rt;
    for (auto oneres : result) {    //转换
        vector<string> cb;
        for (auto td : oneres) {
            string line = "";
            for (auto t : td) {
                if (t == 2)    line += "Q";
                else  line += ".";
            }
            cb.push_back(line);
        }
        rt.push_back(cb);
    }
    return rt;
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注