题目描述
样例输入:
思路
本题考查的是深度优先搜索+回溯。对比N皇后的问题,此题需要在N皇后的基础上再放一个皇后,且条件也要符合皇后在棋盘上的规则,所以我们可以先深搜去放黑皇后,每放一个黑皇后给当前棋盘对应的位置标志为 2
(2
代表黑皇后),所以 dfs
就需要一个标志代表当前是深搜放黑皇后还是白皇后,我们用flag
来表示。2
表示黑皇后,3
表示白皇后。N皇后的基本解法是,我们暴力枚举,我们可以试一试第一行的第一个位置、第二个位置…以此类推。当这一行放好我们就dfs
去下一行搜索,直到行越界且皇后都放完那么这次就是有效的,2n
皇后在此基础上需要添加标志位当一个皇后放完之后,我们需要继续dfs
从0
行开始放下一个皇后,再次到行越界且两个皇后的数量都已经为0
(放完),我们统计次数。
代码
#include <iostream>
#include <vector>
using namespace std;
// 2n皇后问题
int n = 0;
vector< vector<int> >grid;
int black = 0;
int white = 0;
/*
0:代表不能放皇后
1:代表可以放皇后
2:代表黑皇后
3:代表白皇后
*/
int res = 0;
bool isLegal(int row, int col, int flag); // 声明
void dfs(int row , int flag) { // flag代表现在深搜是放黑皇后还是白皇后
if (row == n) {
if (black == 0 && white) {
dfs(0 , 3);
}
else if (black == 0 && white == 0) {
res++;
// 找到结果打印一下棋盘
/*cout << endl << endl;
for (auto& v : grid) {
for (auto val : v) {
cout << val << " ";
}
cout << endl;
}*/
}
return;
}
for (int i = 0; i < n; i++) { // 当前行的每一个位置都遍历一下
if (grid[row][i] == 1 && isLegal(row, i , flag)) {
grid[row][i] = flag;
if (flag == 2) black--;
else white--;
dfs(row + 1 , flag); // 深度优先搜索
// 回溯
grid[row][i] = 1;
if (flag == 2) black++;
else white++;
}
}
}
// flag 2 || 3
bool isLegal(int row , int col , int flag) {
// 行无需检查因为深度优先搜索的时候已经可以确定行不会重复
for (int i = 0; i < n; i++) {
if (grid[i][col] == flag) return false;
}
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (grid[i][j] == flag) return false;
}
for (int i = row, j = col; i < n && j < n; i++, j++) {
if (grid[i][j] == flag) return false;
}
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (grid[i][j] == flag) return false;
}
for (int i = row + 1, j = col - 1; i < n && j >= 0; i++, j--) {
if (grid[i][j] == flag) return false;
}
return true;
}
int main() {
cin >> ::n;
black = white = n;
grid = vector< vector<int> >(n , vector<int>(n));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> grid[i][j];
dfs(0 , 2); // 先放黑皇后
cout << ::res << endl;
return 0;
}