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皇后问题:在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一对角线上的皇后都会自动攻击)。
采用回溯来解决这个问题。
回溯法解决的问题都可以用枚举法解决,对于E中的任意一个元祖,逐个检查其是否满足约束集D,如果满足,就为问题的一个解,枚举法的缺点在于计算量大,而回溯法在搜索过程中,一旦发现原先的选择并不优或者达不到目标,立即回溯到前一步重新选择,简单的说,回溯法的思想就是-此路不通,掉头重新选路,这样能够避免无效搜索,降低了算法复杂度。
回溯法解决问题的一般思路为:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
N皇后的问题可以这样求解,从上至下依次在每一行放置皇后,进行搜索,若在某一行的任意一列放置皇后均不能满足要求,则不再向下搜索,而进行回溯,回溯至有其他列可放置皇后的一行,再向下搜索,直到搜索至最后一行,找到可行解,输出。
Accepted Solution:
class Solution {
public:
vector<vector<string> > solveNQueens(int n)
{
vector<vector<string>> res;
vector<string> board(n, string(n, '.'));
helper(res, board, 0, n);
return res;
}
void helper(vector<vector<string>> &res, vector<string> &board, int row, int n)
{
if (row == n)
res.push_back(board);
for (int clmn = 0; clmn<n; clmn++)
{
if (isValid(board, row, clmn,n))
{
board[row][clmn] = 'Q';
helper(res, board, row + 1, n);
board[row][clmn] = '.';
}
}
}
bool isValid(vector<string> &board, int row, int clmn, int n)
{
for (int i = 0; i<n; i++)
if (board[i][clmn] == 'Q')
return false;
for (int i = 0; i<n; i++)
if ((i + row - clmn) >= 0 && (i + row - clmn) < n && board[i + row - clmn][i] == 'Q')
return false;
for (int i = 0; i<n; i++)
if ((i + row + clmn - n + 1) >= 0 && (i + row + clmn - n + 1) < n && board[i + row + clmn - n + 1][n-1-i] == 'Q')
return false;
return true;
}
};