文章目录
N皇后问题
Leetcode 51题
回溯方法的两种实现
- 利用数组,利用数组下标和值作为行列标号,初始化值和下标相同,求出整个数组的全排列,这样可以避免在横向和纵向上的对比,因为全排列不会有重复的值和下标,只需要考虑两个斜线方向上是否有冲突。
class Solution1 {
public:
vector<vector<string>> solveNQueens(int n) {
vector<int> v;
for (int i = 0; i < n; i++) {
v.push_back(i);
}
vector<vector<string>> ans;
dfs(0, v, n, ans);
return ans;
}
void dfs(int x, vector<int>& v, int n, vector<vector<string>>& ans) {
if (x == n - 1) {
if (chengli(v)) {/*判断是不是都不在同一个斜线方向上*/
vector<string> temp = get_ans1(v, n);/*返回一个结果*/
ans.emplace_back(temp);
return;
}
}
for (int i = x; i < n; i++) {//回溯
swap(v[i], v[x]);
dfs(x + 1, v, n, ans);
swap(v[i], v[x]);
}
}
/*判断是不是都不在同一个斜线方向上*/
bool chengli(vector<int> v) {
bool b = true;
for (int i = 0; i + 1 < v.size(); i++) {
for (int j = i + 1; j < v.size(); j++) {
if (v[i] + i == v[j] + j) {
b = false;
return b;
}
}
}
for (int i = 0; i + 1 < v.size(); i++) {
for (int j = i + 1; j < v.size(); j++) {
if (v[i] - i == v[j] - j) {
b = false;
return b;
}
}
}
return b;
}
/*返回一个结果*/
vector<string> get_ans1(vector<int> v, int n) {
vector<string> ans1;
for (int i = 0; i < n; i++) {
string row = string(n, '.');
row[v[i]] = 'Q';
ans1.emplace_back(row);
}
return ans1;
}
};
- 方法二,也是回溯,逐行查看每一个位置是否可以放置,只需判断当列和右上角和左上角是否有冲突,可以放就加入下一层,成功就回溯。
class Solution2 {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> ans;
vector<string> ans1;
for (int k = 0; k < n; k++) {
string temp = string(n, '.');
ans1.emplace_back(temp);
}
dfs(0, n, ans1, ans);
return ans;
}
void dfs(int row, int n, vector<string>& ans1, vector<vector<string>>& ans) {
if (row == n) {
ans.emplace_back(ans1);
return;
}
for (int j = 0; j < n; j++) {
if (valid(row, j, n, ans1)) {
ans1[row][j] = 'Q';
dfs(row + 1, n, ans1, ans);
ans1[row][j] = '.';
}
}
}
/*判断每列和斜线是否可以放置皇后*/
bool valid(int row, int col, int n, vector<string>ans1) {
bool b = true;
//判断这一列
for (int i = 0; i < n; i++) {
if (ans1[i][col] == 'Q') {
b = false;
return b;
}
}
//判断左上
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (ans1[i][j] == 'Q') {
b = false;
return b;
}
}
//判断右上
for (int i = row, j = col; i >= 0 && j < n; i--, j++) {
if (ans1[i][j] == 'Q') {
b = false;
return b;
}
}
return b;
}
};