【LeetCode】103.N-Queens
題目描述(Hard)
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
'Q'
and '.'
both indicate a queen and an empty space respectively.
題目連結
https://leetcode.com/problems/n-queens/description/
Example 1:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
演算法分析
設定一個數組vector<int>C(n, 0), C[i]表示第i行皇后所在的列編號,即在位置(i, C[i])上放了一個皇后,這樣用一個一維陣列就能記錄整個棋盤。
方法一:對當前行,每次逐列掃描,判斷所在位置是否放置皇后(前面的行的皇后是否衝突),判斷條件,對第i行: 1.是否在同一列C[i]==col;2.是否在同一對角線abs(row-i)==abs(col-C[i]),即兩點不構成正方形,就不在一條對角線上。時間複雜度,空間複雜度。
方法二:記錄皇后已經佔據的列,佔據的主對角線、副對角線,對N×N的棋盤,主對角線和副對角線各2N-1條。對第row行,第i列資料,其所在主對角線位置為row-j+N-1,其所在副對角線的位置為row+j。時間複雜度
,空間複雜度。
提交程式碼(方法一):
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> result;
vector<int> C(n, -1);
dfs(result, C, 0);
return result;
}
void dfs(vector<vector<string>> &result, vector<int> &C, int row) {
const int N = C.size();
if (row == N) {
vector<string> solution;
for (int i = 0; i < N; ++i) {
string S(N, '.');
S[C[i]] = 'Q';
solution.push_back(S);
}
result.push_back(solution);
return;
}
// 逐列掃描
for (int i = 0; i < N; ++i) {
if (!isValid(C, row, i)) continue;
C[row] = i;
dfs(result, C, row + 1);
C[row] = -1;
}
}
bool isValid(vector<int>& C, int row, int col) {
for (int i = 0; i < row; ++i) {
// 如果在相同列
if (C[i] == col) return false;
// 在對角線上
if (abs(row - i) == abs(col - C[i])) return false;
}
return true;
}
};
提交程式碼(方法二):
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
columns = vector<bool>(n, false);
main_diag = vector<bool>(2 * n - 1, false);
anti_diag = vector<bool>(2 * n - 1, false);
vector<vector<string>> result;
vector<int> C(n, -1);
dfs(result, C, 0);
return result;
}
private:
vector<bool> columns;
vector<bool> main_diag;
vector<bool> anti_diag;
void dfs(vector<vector<string>> &result, vector<int> &C, int row) {
const int N = C.size();
if (row == N) {
vector<string> solution;
for (int i = 0; i < N; ++i) {
string S(N, '.');
S[C[i]] = 'Q';
solution.push_back(S);
}
result.push_back(solution);
return;
}
// 逐列掃描
for (int i = 0; i < N; ++i) {
bool valid = !columns[i] && !main_diag[row - i + N - 1]
&& !anti_diag[row + i];
if (!valid) continue;
columns[i] = main_diag[row - i + N - 1]
= anti_diag[row + i] = true;
C[row] = i;
dfs(result, C, row + 1);
C[row] = -1;
columns[i] = main_diag[row - i + N - 1]
= anti_diag[row + i] = false;
}
}
};