leetcode原题链接:N皇后
题目描述
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例 1:
输入:n = 4 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1 输出:[["Q"]]
提示:
1 <= n <= 9
解题方法:回溯法。backtrack(n, int x, tmp, q_mp, results)表示对第x行放置皇后(0<= x < n),tmp用于保存临时解, q_mp用于保存[0, x -1]已经放置了皇后的每一个<x0, y0>,针对x,寻找对应的所有可能的y,这些y必须满足条件,即待放置皇后的(x,y)不与已经放置了皇后的(x0, y0)中的任何一个皇后不能在同一列,也不能在同一个斜率为1或者-1的对角线上。
C++代码
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <utility> //pair
class Solution {
public:
std::vector<std::vector<std::string>> solveNQueens(int n) {
std::vector<string> tmp(n, std::string(n, '.'));//将每一行的tmp都设置为空位(.)
std::map<int, int> q_mp; //保存每一行的皇后对应的列。x->y
std::vector<std::vector<string>> results;//保存最终的结果
backtrack(n, 0, tmp, q_mp, results);
return results;
}
// 对第i行放置皇后
// q_mp 保存当前已经放了Q的(x,y)
void backtrack(int n, int x, std::vector<string>& tmp,
std::map<int, int>& q_mp,
std::vector<std::vector<string>>& results) {
if (x == n) { //每一行都放置好了皇后
results.emplace_back(tmp);
return;
}
// 对第x行不同的列放置皇后
for (int y = 0; y < n; y++) {
if (check(x, y, q_mp)) {
// 对第x行操作
tmp[x][y] = 'Q';
q_mp.insert({x, y});
backtrack(n, x + 1, tmp, q_mp, results); // 对下一行处理
// 对第x行取消操作
tmp[x][y] = '.';
q_mp.erase(x);
}
}
}
// 判断(x, y)与当前已经赋值过的(x0, y0)是否冲突
bool check(int x, int y, std::map<int, int>& q_mp) {
for (const auto& vp : q_mp) {
int x0 = vp.first;
int y0 = vp.second;
// 不同列
if (y0 == y) {
return false;
}
// 不能在对角线(包括主对角线和斜对角线)
if (std::abs(y - y0) == x - x0) {
return false;
}
}
return true;
}
};