每天一道LeetCode-----n皇后问题

来源:互联网 发布:中建八局四公司知乎 编辑:程序博客网 时间:2024/06/06 00:19

N-Queens

原题链接N-Queens
这里写图片描述
n皇后问题,和数独问题一样,都是回溯法的经典题目。
n皇后问题约束是任意两个皇后不能在一行,不能在一列,不能在同一个45度直线,不能在同一个135度直线上。所以求解时需要记录

  • 当前行是否已经存在一个皇后
  • 当前列是否已经存在一个皇后
  • 当前位置所在的45度直线上是否已经存在一个皇后
  • 当前位置所在的135度直线上是否已经存在一个皇后

因为n行n个皇后,所以每一行有且仅有一个皇后,那么可以不需要记录当前行是否已经存在皇后,只要在当前行找到一个位置容纳皇后,就开始在下一行寻找,即每一行遍历右边列,找到满足后三个条件的位置即可。

所有的约束条件都可以用数组记录,即

  • flag_col[column]表示column列是否已经存在一个皇后
  • flag_45[p]表示位置[row, column]所在的45度直线是否出现过皇后,其中p是row和column的函数
  • flag_135[q]表示位置[row, column]所在的135度直线是否出现过皇后,其中q是row和column的函数

比较不要记录的就是45度和135度直线上的情况,可以利用数学思维简化。

  • 对于45度直线,可知斜率为1,即解析式可以写成y = x + b。那么对于在同一条45度直线的点,截距b是一定的,所以可以用y - x来代表某一条45度直线,所以可以另m = column - row。但是column可能会小于row,导致m为负值,所以可以将m增加n - 1让m变为正值,即m = n - 1 + column - row
  • 对于135度直线,可知斜率为-1,同理可知另m = column + row,此时不存在m为负值的情况,无须加n - 1
  • 不过需要注意的是flag_45和flag_135数组的大小是2 * n - 2,设置成2 * n即可
class Solution {public:    vector<vector<string>> solveNQueens(int n) {        vector<vector<string>> res;        vector<string> cur(n, string(n, '.'));        vector<int> flag_col(n, 1), flag_45(2 * n, 1), flag_135(2 * n, 1);        solveNQueens(n, 0, cur, res, flag_col, flag_45, flag_135);        return res;    }private:    void solveNQueens(int n, int row, vector<string>& cur, vector<vector<string>>& res, vector<int>& flag_col, vector<int>& flag_45, vector<int>& flag_135)    {        if(row >= n)        {            res.emplace_back(cur);            return;        }        /* 回溯法 */        for(int i = 0; i < n; ++i)        {            if(flag_col[i] && flag_45[n - 1 + i - row] && flag_135[i + row])            {                cur[row][i] = 'Q';                flag_col[i] = flag_45[n - 1 + i - row] = flag_135[i + row] = 0;                solveNQueens(n, row + 1, cur, res, flag_col, flag_45, flag_135);                cur[row][i] = '.';                flag_col[i] = flag_45[n - 1 + i - row] = flag_135[i + row] = 1;            }        }    }};
原创粉丝点击