蓝桥杯 2n皇后 dfs

问题描述
  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
  输入的第一行为一个整数n,表示棋盘的大小。
  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
  输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
思路:先放黑皇后,将黑皇后合理的摆放好后,再放白皇后。放黑皇后时,限制条件为该点不能为0,因为是从上到下遍历每一行,一行只放一个黑皇后,所以只需考虑该点所在的列是否放过皇后(vy[10]数组标记该列是否放过皇后,该点值为1表示该列已经放了一个黑皇后,不能再放黑皇后;该点值为2表示该列已经放了一个白皇后,不能再放白皇后;该点值为3表示该列已经放了一个黑皇后和一个白皇后,不能再放黑皇后和白皇后),该点所在的左对角线是否放过黑皇后(vd1[20]数组,含义同上),该点所在右对角线是否放过黑皇后(vd2[20]数组,含义同上)。

  每在点(i,j)放一个黑皇后,将该点mp[i][j]置为0,表示该点已经被用过。黑皇后放完后,开始放白皇后,判断条件同黑皇后。

参考于计蒜客蓝桥杯省赛训练营的例题讲解
AC代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int mp[10][10]; //存储地图
 4 int vy[10]; //存储该列的信息
 5 int vd1[20]; //存储左对角线信息
 6 int vd2[20]; //存储右对角线信息
 7 int n, ans;
 8 void dfs(int x, int p) { //参数x表示当前搜索到第几行,参数p表示当前在放什么颜色的皇后,p = 1表示放黑皇后,p = 2表示放白皇后
 9     if (x == n && p == 2) { //从第0行 ~ n - 1行遍历,若当前遍历到第n行,且白皇后已放完,方案数加一
10         ans++;
11         return;
12     }
13     if (x == n) { //从第0行 ~ n - 1行遍历,若当前遍历到第n行,表示黑皇后已放完,开始从第0行放白皇后
14         dfs(0, p + 1);  //将p变为2,表示开始遍历白皇后
15         return;
16     }
17     for (int i = 0; i < n; i++) { //遍历每一列
18         //在该点可以放皇后的条件:
19             //该点不为0; mp[x][i] != 0
20             //该点所在的列没有同颜色皇后; vy[i] != 3 && vy[i] != p
21             //该点所在的左对角线没有同颜色皇后; vd1[x + i] != 3 && vd1[x + i] != p
22             //该点所在的右对角线没有同颜色皇后; vd2[x - i + n] != 3 && vd2[x - i + n] != p
23         if (mp[x][i] != 0 && vy[i] != 3 && vy[i] != p && vd1[x + i] != 3 && vd1[x + i] != p && vd2[x - i + n] != 3 && vd2[x - i + n] != p) {
24             mp[x][i] = 0; //将该点置为0,表示将皇后放在该点
25             vy[i] += p; //更新该点所在的列
26             vd1[x + i] += p; //更新该点所在的左对角线
27             vd2[x - i + n] += p; //更新该点所在的右对角线
28             
29             dfs(x + 1, p); //搜索下一行
30             
31             vy[i] -= p; //回溯,恢复现场
32             vd1[x + i] -= p;
33             vd2[x - i + n] -= p;
34             mp[x][i] = 1;
35         }
36     }
37 }
38 int main() {
39     cin >> n;
40     for (int i = 0; i < n; i++) { //输入棋盘
41         for (int j = 0; j < n; j++) {
42             cin >> mp[i][j];
43         }
44     }
45     //先放黑皇后,再放白皇后
46     dfs(0, 1); //从第0行开始搜索,1表示先放黑皇后
47     cout << ans << endl; //输出方案数
48     return 0;
49 }
原文地址:https://www.cnblogs.com/fx1998/p/12584061.html