- 问题来源
- 问题简介
在一个n * n的格子里放置n个皇后,要求每任意两个皇后都不能处于同一行、同一列或者对角线上(45度或者135度)。返回总共有多少种排法。
解题思路
从第一行到最后一行,每次从第一个到最后一个,都尝试放置一个皇后,若符合要求,则计数加一。那么有如下问题:如何判断某个位置是否可以放置一个皇后?
- 每放置一个皇后就对以前放置过的皇后进行逐一检查
- 设置状态位,定义每一行,每一列,每一斜线上的格子是否可放置
- 如何设置以皇后为基点的斜线为不可放置状态
若两点(i1, j1)、(i2, j2)满足 i1 + j1 == i2 + j2,或 j1 - i1 == j2 - i2,则两点处于同一条斜线上(45度或135度)
- 如何设置以皇后为基点的斜线为不可放置状态
时间复杂度 | 空间复杂度 |
---|---|
… | … |
Code
#include <iostream>
#include <stack>
#include <vector>
#include <functional>
using namespace std;
class Solution {
private:
bool *flag;
int count;
void solve(int row, int col, int n) {
if (row == n - 1) {
count++;
return;
}
flag[col] = flag[n + row + col] = flag[4 * n - 2 + col - row] = false;
row++;
for (int i = 0; i < n; i++) {
if (flag[i] && flag[n + row + i] && flag[4 * n - 2 + i - row]) {
solve(row, i, n);
}
}
row--;
flag[col] = flag[n + row + col] = flag[4 * n - 2 + col - row] = true;
}
public:
Solution() { flag = nullptr; }
~Solution() { delete[] flag; }
void init(int n) {
count = 0;
if (flag) {
delete[] flag;
}
flag = new bool[5 * n - 2];
for (int i = 5 * n - 2 - 1; i--;) {
/*
flag[0] to flag[n - 1] to indicate if the column had a queen before.
flag[n] to flag[3 * n - 2] to indicate if the 45° diagonal had a queen before.
flag[3 * n - 1] to flag[5 * n - 3] to indicate if the 135° diagonal had a queen before.
*/
flag[i] = true;
}
}
int totalNQueens(int n) {
if (n < 2) {
return n;
}
init(n);
for (int i = 0; i < n; i++) {
solve(0, i, n);
}
return count;
}
};
int main() {
Solution nq;
for (int i = 0; i < 10; i++) {
cout << i << ": " << nq.totalNQueens(i) << endl;
}
return 0;
}