zoukankan      html  css  js  c++  java
  • [蓝桥杯][基础练习VIP]2n皇后问题

    问题描述
      给定一个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
     
     
     
    蓝桥杯的话,最难的和出现最多的应该就是dfs,bfs和动态规划了,这也是一道典型的dfs,基本思路是穷尽尝试,如果某次尝试失败,则退回上一步重新选择。
    接下来对这一题作具体分析:
    1.要找出所有可能,每种可能要求同行,同列,同对角线上不能出现同种颜色皇后,首先想到的应该是先放一种颜色的皇后,再放另一种。
    那么先放黑皇后,再放白皇后,每种皇后都从第一行遍历到最后一行,每行再逐列尝试。
    2.在每次放皇后时,需要判断同行,同列,同对角线上是否已经出现了同种颜色的皇后,所以每次放过皇后后要标记这三个值。接下来讲如何标记这三个值:
    3.因为是从第一行遍历到最后一行,所以不需要考虑行,而列只需要设置一个数组,每次放入一个皇后,在相应的vis数组标记为1。
    至于同对角线,有两种情况,从左下到右上的对角线,我暂且称之为斜1;从左上到右下,记作斜2;
    (1)很容易可以看出在斜1同一条对角线上的横纵坐标相加是一个固定的数,且每条对角线不会重复,0,2,4,6.....所以直接把这个相加之后固定的数作为数组的下标,每次放入之后标记为1;
    (2)同理,斜2同一条对角线上横纵坐标相减为一个固定的数,为了防止出现负数,统一加7
    (具体见18,19行和42,43行)
    到这里这道题的难点就结束了,代码中有更详细的注释
    
    
     1 #include<iostream>
     2 using namespace std;
     3 int n ,ans = 0;
     4 int qp[8][8];//棋盘
     5 // 0不能放;1能放;2黑皇后;3白皇后
     6 int lieblack[8]{ 0 }, liewhite[8]{ 0 };//  0/1标记该列是否被黑/白皇后占用
     7 int xie1black[20]{ 0 }, xie2black[20]{ 0 }, xie1white[20]{ 0 }, xie2white[20]{ 0 };
     8 //标记左斜行和右斜行
     9 void dfswhite(int hang) //参数为当前的行数
    10 {
    11     if (hang == n) //当白皇后最后一行也已经放完之后
    12     {
    13         ans++;     //已经是一种成功放置的方法
    14         return ;
    15     }
    16     for (int lie = 0; lie < n; lie++) //在每行中遍历
    17     {
    18         if (qp[hang][lie] == 1 && liewhite[lie] == 0 && xie1white[hang + lie] == 0
    19             && xie2white[hang - lie + 7] == 0)//判断条件依次为,棋盘是否能放;该列是否被同颜色皇后占用;
    20                                               //斜1对角线是否被占用;斜2对角线是否被占用;
    21         {
    22             qp[hang][lie] = 2;              //放置皇后,依次标记
    23             liewhite[lie] = 1;
    24             xie1white[hang + lie] = 1;
    25             xie2white[hang - lie + 7] = 1;
    26             dfswhite(hang + 1);      //该行已放置,进入下一行
    27             qp[hang][lie] = 1;       //回溯,移除标记
    28             liewhite[lie] = 0;
    29             xie1white[hang + lie] = 0;
    30             xie2white[hang - lie + 7] = 0;
    31         }
    32     }
    33 }
    34 void dfsblack(int hang)
    35 {
    36     if (hang == n)  //当黑皇后最后一行也已经放置
    37     {
    38         dfswhite(0);//开始放置白皇后
    39         return ;
    40     }
    41     for (int lie = 0; lie < n; lie++)  //与dfswhite同理
    42     {
    43         if (qp[hang][lie] == 1 && lieblack[lie] == 0 && xie1black[hang + lie] == 0 
    44             && xie2black[hang - lie + 7] == 0)
    45         {
    46             qp[hang][lie] = 3;
    47             lieblack[lie] = 1;
    48             xie1black[hang + lie] = 1;
    49             xie2black[hang - lie + 7] = 1;
    50             dfsblack(hang + 1);
    51             qp[hang][lie] = 1;
    52             lieblack[lie] = 0;
    53             xie1black[hang + lie] = 0;
    54             xie2black[hang - lie + 7] = 0;
    55         }
    56     }
    57 }
    58 int main()
    59 {
    60     cin >> n;
    61     for (int i = 0; i < n; i++)
    62     {
    63         for (int j = 0; j < n; j++)
    64         {
    65             cin >> qp[i][j];
    66         }
    67     }
    68     dfsblack(0);//从第一行开始防止黑皇后,全部放置完后再放置白皇后
    69     cout << ans;
    70 }
     
  • 相关阅读:
    Servlet Filter
    Analysis of Web.xml in Hello1 project
    Introduction of Annotation
    Analysis of container and Injection in Java, their history and future.
    Maven + Glassfish 实现hello
    java Building tool
    HTTP RFC(自学心得)
    URI和URL
    Git 版本控制
    Oracle RAC 全局等待事件 gc current block busy 和 gc cr multi block request 说明--转载(http://blog.csdn.net/tianlesoftware/article/details/7777511)
  • 原文地址:https://www.cnblogs.com/longwind7/p/14561388.html
Copyright © 2011-2022 走看看