zoukankan      html  css  js  c++  java
  • 蓝桥杯 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 }
  • 相关阅读:
    课堂练习
    软件工程课堂练习二维数组子数组和最大值,只要连续就好
    结对项目电梯调度
    第二次课堂练习
    软件工程课堂练习二维数组子数组和的最大值
    敏捷开发方法
    软件工程个人作业
    电梯调度
    创意
    02合并frame
  • 原文地址:https://www.cnblogs.com/fx1998/p/12584061.html
Copyright © 2011-2022 走看看