凌云的博客

成功=工作+游戏+少说空话

LeetCode 算法题 51. N-Queens

分类:algorithm| 发布时间:2016-10-15 14:14:00


题目

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

For example,

There exist two distinct solutions to the 4-queens puzzle:

[
    [".Q..",  // Solution 1
     "...Q",
     "Q...",
     "..Q."],

     ["..Q.",  // Solution 2
      "Q...",
      "...Q",
      ".Q.."]
]

题意

求出 n 皇后问题的所有解法。

解法

使用回朔法可以解决这个问题。

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> ret;
        string row(n, '.');
        vector<string> board(n, row);
        solve(board, n, 0, ret);
        return ret;
    }

    void solve(vector<string> &board, int n, int x, vector<vector<string>> &ret) {
        if (x == n) {
            ret.push_back(board);
            return;
        }

        for (int i = 0; i < n; ++i) {
            if (is_valid(board, n, x, i)) {
                board[x][i] = 'Q';
                solve(board, n, x + 1, ret);
                board[x][i] = '.';
            }
        }
    }

    bool is_valid(vector<string> &board, int n, int x, int y) {
        for (int i = 0; i < n; ++i) {
            if (i != x && board[i][y] == 'Q')
                return false;

            // back-diagonal
            int j = y - (x - i);
            if (j >= 0 && j < n && board[i][j] == 'Q')
                return false;

            // diagonal line
            j = y + (x - i);
            if (j >= 0 && j < n && board[i][j] == 'Q')
                return false;
        }

        return true;
    }
};

在判断一个位置是否合法时,需要判断这一列,45 度角线以及 135 度角线是否有另一个 Q。 可以通过 3 个辅助数组来简化判断。

/*    | | |                / / /             \ \ \
 *    O O O               O O O               O O O
 *    | | |              / / / /             \ \ \ \
 *    O O O               O O O               O O O
 *    | | |              / / / /             \ \ \ \
 *    O O O               O O O               O O O
 *    | | |              / / /                 \ \ \
 *   3 columns        5 45° diagonals     5 135° diagonals    (when n is 3)
 */
class Solution {
public:
    std::vector<std::vector<std::string> > solveNQueens(int n) {
        vector<vector<string> > res;
        vector<string> board(n, string(n, '.'));
        vector<int> flag_col(n, 1), flag_45(2 * n - 1, 1), flag_135(2 * n - 1, 1);
        solveNQueens(res, board, flag_col, flag_45, flag_135, 0, n);
        return res;
    }
private:
    void solveNQueens(vector<vector<string> > &res, vector<string> &board, vector<int> &flag_col, vector<int> &flag_45, vector<int> &flag_135, int row, int &n) {
        if (row == n) {
            res.push_back(board);
            return;
        }

        for (int col = 0; col != n; ++col)
            if (flag_col[col] && flag_45[row + col] && flag_135[n - 1 + col - row]) {
                flag_col[col] = flag_45[row + col] = flag_135[n - 1 + col - row] = 0;
                board[row][col] = 'Q';
                solveNQueens(res, board, flag_col, flag_45, flag_135, row + 1, n);
                board[row][col] = '.';
                flag_col[col] = flag_45[row + col] = flag_135[n - 1 + col - row] = 1;
            }
    }
};