题目描述:
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.."] ]一开始搞错了规则,以为王后是吃范围1格内的棋子( ̄_ ̄|||) ,后来怎么改都不对才发现是吃横纵双斜线的棋子……
搞明白规则以后,用BF来解。一开始思路是找到一个合适的点,然后将这个点的攻击范围全部做标记,后面遍历的时候跳过这些点,这样写出来的代码很冗长,然后n=9的时候TLE了……
其实我们观察下会发现,每一行最多只能存在一个Queen,所以要放下n个Queen,则每行有且仅有一个Queen。
对两个点A[i][j]、B[m][n]有:
1、若i==m,则同行
2、若j==n,则同列
3、若i+j==m+n,则在同一条右斜线上
4、若i-j==m-n,则在同一条左斜线上
有了以上规则题目解起来就很简单了,只要递归记录下每个Queen的坐标,对一个新点只要判定下上面的条件就可以知道是否合法。
代码如下:
class Solution {
public:
int N;
vector<vector<string> > solveNQueens(int n) {
N = n;
vector<vector<string>> ret;
string line;
for (int i = 0; i < n; i++)
line += '.';
vector<string> path(n, line);
vector<int> rec;
solve(path, n, ret, rec);
return ret;
}
void solve(vector<string> &path, int n, vector<vector<string>> &ret, vector<int> &rec){
if (!n){
vector<string> temp = path;
ret.push_back(temp);
return;
}
int i = rec.size();
for (int j = 0; j < N; j++){
int m(0);
for (m = 0; m < rec.size(); m++)
if (rec[m] == j || m + rec[m] == i + j || m - rec[m] == i - j)
break;
if (m < rec.size())
continue;
rec.push_back(j);
path[i][j] = 'Q';
solve(path, n - 1, ret, rec);
path[i][j] = '.';
rec.pop_back();
}
}
};