题目:
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.
N皇后问题是在一个n x n 的棋盘上放置N个皇后,使得每个皇后不同行、不同列也不能在同一条斜线上。
给定一个整数n,返回所有不同的可能性。每个结果包含不同的设置,放置Q和 . 分别代表一个皇后和空格。
For example,
There exist two distinct solutions to the 4-queens puzzle:
[ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ]
思路:
1、这里可以用数组vector<int> q(n,0),q[i]表示第 i 行的queen放在 q[i] 列,这样就转化成求0~n-1总共 n 个数的全排列,全排列可以参考:http://blog.csdn.net/u012243115/article/details/42965749 。然后对这n! 个全排列进行筛选,这个全排列保证了棋盘图的每个皇后的行列不同,还要判断每个皇后的位置不在一条斜线上,详情见代码。
2、依次放置每行的皇后。在放置的时候,要保持当前的状态为合法,即与上面行的皇后不冲突,即当前放置位置的同一行、同一列、同一斜线线上都不存在皇后。
3、结合上面两种方法。
代码1:
class Solution {
public:
vector<vector<string> > solveNQueens(int n)
{
vector<vector<string> > result;//保存结果
vector<int> q(n,0);//q[i]表示棋盘上第i行的'Q'位于q[i]列,下面的for循环初始化使得每个'Q'位于不同行不同列
for(int i = 0 ; i < n ; i++) //初始化q
{
q[i] = i;
}
DFS(n,0,q,result);//调用DFS构造棋盘图
return result;
}
void DFS(int n , int start , vector<int> &q , vector<vector<string> > &result)
{
if(start == n)
{
//筛选全排列
for(int i = 0 ; i < n ; i++)
{
for(int j = i + 1 ; j < n ; j++)
{
if((j-i) == abs(q[j]-q[i])) //如果两个皇后在一条斜线上,则此种排列不符合条件,直接返回
{
return;
}
}
}
//如果没有被筛选掉,则构造棋盘图
vector<string> cur(n,string(n,'.'));//先构造一个全部为'.'的图,然后再设置皇后的位置
for(int i = 0 ; i < n ; i++)
{
cur[i][q[i]] = 'Q';//把第i行,第q[i]列的元素设置为皇后
}
result.push_back(cur);
return;
}
for(int i = start ; i < n ; i++)
{
swap(q[i],q[start]);
DFS(n,start+1,q,result);//递归求全排列
swap(q[i],q[start]);
}
}
};
代码2:
class Solution {
private:
vector<vector<string> > result;
public:
vector<vector<string> > solveNQueens(int n)
{
vector<string> cur(n, string(n,'.'));
DFS(cur, 0);
return result;
}
void DFS(vector<string> &cur, int row)
{
if(row == cur.size())
{
result.push_back(cur);
return;
}
for(int col = 0; col < cur.size(); col++)
{
if(isValid(cur, row, col))
{
cur[row][col] = 'Q';//在当前位置放置皇后之前检查是否与上面的皇后冲突,不冲突后才能放置
DFS(cur, row+1);//递归调用下一行
cur[row][col] = '.';//恢复当前位置
}
}
}
//判断在cur[row][col]位置放一个皇后,是否是合法的位置
//已经保证了每行一个皇后,只需要判断列是否合法以及对角线是否合法。
bool isValid(vector<string> &cur, int row, int col)
{
//列
for(int i = 0; i < row; i++)
{
if(cur[i][col] == 'Q')
return false;
}
//左上角对角线(只需要判断对角线上半部分,因为后面的行还没有开始放置)
for(int i = row-1, j=col-1; i >= 0 && j >= 0; i--,j--)
{
if(cur[i][j] == 'Q')
return false;
}
//右上角对角线(只需要判断对角线上半部分,因为后面的行还没有开始放置)
for(int i = row-1, j=col+1; i >= 0 && j < cur.size(); i--,j++)
{
if(cur[i][j] == 'Q')
return false;
}
return true;
}
};
代码3:
class Solution {
private:
vector<vector<string> > result;
public:
vector<vector<string> > solveNQueens(int n)
{
vector<int> q(n,-1);
DFS(n,q, 0);
return result;
}
void DFS(int n , vector<int> &q, int row)
{
if(row == n)
{
vector<string> cur(n,string(n,'.'));
for(int i = 0 ; i < n ; i++)
{
cur[i][q[i]] = 'Q';
}
result.push_back(cur);
return;
}
for(int col = 0; col < n; col++)
{
if(isValid(q, row, col))
{
q[row] = col;//在当前位置放置皇后之前检查是否与上面的皇后冲突,不冲突后才能放置
DFS(n,q,row+1);//递归调用下一行
q[row] = -1;//恢复当前位置
}
}
}
bool isValid(vector<int> q, int row, int col)
{
for(int i = 0 ; i < row ; i++)
{
if(q[i] == col || (row - i) == abs(col - q[i]))
return false;
}
return true;
}
};