给定一个 n*nn∗n 的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入 nn 个黑皇后和 nn个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条斜线(包括正负斜线)上,任意的两个白皇后都不在同一行、同一列或同一条斜线(包括正负斜线)上。问总共有多少种放法?nn 小于等于 88。

输入格式

  输入的第一行为一个整数 nn,表示棋盘的大小。

  接下来 nn 行,每行 nn 个 00 或 11 的整数,如果一个整数为11,表示对应的位置可以放皇后,如果一个整数为 00,表示对应的位置不可以放皇后。

输出格式

输出一个整数,表示总共有多少种放法。

样例输入1

4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

样例输出1

2

样例输入2

4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1

样例输出2

0

要想理解2n皇后的做法就需要我们先理解n皇后问题。

这里贴上百度的解释:https://baike.baidu.com/item/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98/11053477?fr=aladdin

n皇后问题其实不是很难。它用到思想是算法中的回溯思想。

如果我想找到所有的n皇后的有效解个数,那么我们应该从第一层开始。在这里我准备边讲代码边分析、

开始的时候我们先定义三个全局的数组变量

int num[8][8];
int location[8];
int maxn=-1;

这三个变量分别表示为 不同位置的权值(因为这道8皇后问题是为了找到所有情况中权值和最大的那个情况)、这八行数的各行的位置记录、所有情况中的最大值是多少。

这里为什么要定义全局变量呢?我下面会讲到。

之后就要看主函数了,

int main(){
int k;
cin>>k;
while(k--){
for(int i=;i<;i++){
for(int h=;h<;h++){
cin>>num[i][h];
}
}
Queen();
cout<<maxn<<endl; } }

主函数很简单,就是循环赋值然后调用Queen回溯,然后得出来最大值maxn并输出。

下面是关键代码:

int valid(int rows,int columns){
for(int i=;i<rows;i++){
if(columns==location[i]||abs(rows-i)==abs(columns-location[i])) return ; }
return ;
}

这里给出的函数是一个“剪枝函数”,(例如现在走到了第三行,就要循环第一、第二行,找出前两行的皇后存在的位置,然后与第三行的皇后位置比较-----①如果第三行皇后与以上两行任意一个皇后在同一列②或者同一对角线(主对角线或者非主对角线均可以,代码:abs(rows-i)==abs(columns-location[i])),那么返回0,否则说明第三行的这个位置可以放皇后,就返回1)

此时我们知道了“剪枝函数”也就体现了回溯算法的思想了,因为按照我的理解,回溯就是(完全遍历的所有情况-大部分一开始就不满足条件的情况),所以这个函数其实很重要。

之后我们写出来回溯的函数

int Queen(int row){
if(row == ) {
int current_max=;
for(int i=;i<;i++){
current_max+=num[i][location[i]];
}
maxn=max(current_max,maxn);
}
else{
for(int n=;n<;n++){
if(valid(row,n)){
location[row]=n;
Queen(row+);
}
}
}
}

在这个函数中,我们传入的row是行号,第一个if是跳出循环的条件——当row循环了八次之后完成循环(也就说明这八次循环得到了一种最优解的情况),else里面是循环八次分别找每一行的符合要求的解。

如果满足valid,那么记录第row行的列号,然后递归到下一层函数。

*****这里我们为什么要定义全局变量呢?这里,我们要知道程序在计算的时候是按照顺序执行的。只有8^8种情况中的第一种结束了,才会计算下一种情况。所以这个全局变量会被每一个子问题分别使用,并且下一个子问题会不断覆盖上一个子问题的全局变量中的值。

之后我们有了n皇后的基础之后,解决2n或者多n皇后问题就很简单了。

在2n皇后的要求中(我开始写的计蒜课的算法题目),我们知道它多了一个条件,就是我令一部分位置不能放棋子。这个时候我们就要在 Queen函数中循环列的时候判断一下这个位置是否可用,只有可用的时候才能进入判读。

而2n皇后其实就是先计算第一个n皇后,然后得出来一个n皇后的表,之后在计算另一个皇后,这个时候第二种皇后的情况就要除去第一个n皇后已经放入的位置。就是相当于那个”能否使用表”稍微复杂了一点而已。。。

这里放上代码:

#include<iostream>
#include<cmath>
using namespace std;
int board[][];
int all=;
int black_location[];
int white_location[];
int w_valid(int rows,int columns){
for(int i=;i<rows;i++){
if(columns==white_location[i]||abs(rows-i)==abs(columns-white_location[i])) return ; }
return ;
} int b_valid(int rows,int columns){
for(int i=;i<rows;i++){
if(columns==black_location[i]||abs(rows-i)==abs(columns-black_location[i])) return ; }
return ;
}
int Queen_b(int cur,int n){
if(cur==n){
all++;
}
else{
for(int h=;h<n;h++){
if(h==white_location[cur]||board[cur][h]==) continue;
else{
if(b_valid(cur,h)){
black_location[cur]=h;
Queen_b(cur+,n);
}
}
}
}
} int Queen_w(int cur,int n){
if(cur==n) {
Queen_b(,n);
}
else{
for(int i=;i<n;i++){
if(board[cur][i]==) continue;
if(w_valid(cur,i)){
white_location[cur]=i;
Queen_w(cur+,n);
}
}
}
}
int main(){
int n;
cin>>n;
for(int i=;i<n;i++){
for(int h=;h<n;h++)
cin>>board[i][h];
}
Queen_w(,n);
cout<<all;
}

多注意细节就好,代码量有点大,有什么不懂的地方大家给我留言。

--------------------------------------------------------------------------------------Made By Pinging

  

计蒜课--2n皇后、n皇后的解法(一般操作hhh)的更多相关文章

  1. German Collegiate Programming Contest 2015 计蒜课

    // Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...

  2. 算法复习周------“动态规划之‘最长公共子序列’”&&《计蒜课》---最长公共子串题解

    问题描述: 这个问题其实很容易理解.就是给你两个序列X={x1,x2,x3......xm} Y={y1,y2,y3......ym},要求找出X和Y的一个最长的公共子序列. 例:Xi={A, B, ...

  3. 动态规划---等和的分隔子集(计蒜课)、从一个小白的角度剖析DP问题

    自己还是太菜了,算法还是很难...这么简单的题目竟然花费了我很多时间...在这里我用一个小白的角度剖析一下这道题目. 晓萌希望将1到N的连续整数组成的集合划分成两个子集合,且保证每个集合的数字和是相等 ...

  4. 计蒜课/ 微软大楼设计方案/中等(xjb)

    题目链接:https://nanti.jisuanke.com/t/15772 题意:中文题诶- 思路:对于坐标为p1(x1, y1), p2(x2, y2) 的两个核心, 其中 x1 <= x ...

  5. 计蒜课/UCloud 的安全秘钥(hash)

    题目链接:https://nanti.jisuanke.com/t/15768 题意:中文题诶- 思路:直接hash就好了,当时zz了没想到... 代码: #include <iostream& ...

  6. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  7. 2019计蒜客信息学提高组赛前膜你赛 #2(TooYoung,TooSimple,Sometimes Naive

    计蒜客\(2019CSP\)比赛第二场 巧妙爆零这场比赛(我连背包都不会了\(QWQ\) \(T1\) \(Too\) \(Young\) 大学选课真的是一件很苦恼的事呢! \(Marco\):&qu ...

  8. C#中八皇后问题的递归解法——N皇后

    百度测试部2015年10月份的面试题之——八皇后. 八皇后问题的介绍在此.以下是用递归思想实现八皇后-N皇后. 代码如下: using System;using System.Collections. ...

  9. 计蒜客 作弊揭发者(string的应用)

    鉴于我市拥堵的交通状况,市政交管部门经过听证决定在道路两侧安置自动停车收费系统.当车辆驶入车位,系统会通过配有的摄像头拍摄车辆画面,通过识别车牌上的数字.字母序列识别车牌,通过连接车管所车辆信息数据库 ...

随机推荐

  1. maven 新建项目时修改默认jre路径

    新建maven项目时,JRE System Library默认为J2SE-1.5 如果想修改为1.7,修改maven的settings.xml ,在profiles中添加 <profile> ...

  2. socket的bind函数是不是只能绑定本地IP,不能绑定外网IP么?

    参考: https://bbs.csdn.net/topics/391024376 别瞎猜测. 所谓bind,就是指绑定本地接受端口. 指定ip,是为了分辨多ip主机. --------------- ...

  3. Linux 快照

    10个方法助你轻松完成Linux系统恢复 提交 我的留言 加载中 已留言 这也就是为什么系统恢复功能会让人感觉如此神奇.你可以很快地重新回到工作中去,就像什么事情都没有发生一样,也不用去管造成系统故障 ...

  4. Deepin-安装laravel

    首先获取到composer.phar wget https://getcomposer.org/download/1.6.3/composer.phar 下载以后移动到目标区域 sudo mv com ...

  5. Linux 编译安装Boost

    linux平台下要编译安装除gcc和gcc-c++之外,还需要两个开发库:bzip2-devel 和python-devel,因此在安装前应该先保证这两个库已经安装: #yum install gcc ...

  6. 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)

    如约而至,Java 10 正式发布!   3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...

  7. linux下weblogic11g成功安装后,启动报错Getting boot identity from user

    <2015-7-1 下午05时46分33秒 CST> <Info> <Management> <BEA-141107> <Version: Web ...

  8. Ubuntu14.04 64bit下Caffe + CUDA 6.5安装详细步骤

    不多说,直接上干货! 笔者花了很长时间才装完,主要是cuda安装和opencv安装比较费劲,cuda找不到32位的安装包只好重装64位的ubuntu系统,opencv 也是尝试了很久才解决,这里建议用 ...

  9. 3.2.1 配置构建Angular应用——简单的笔记存储应用——编辑功能

    本节我们会接着上节课的内容,继续来完成使用Angular来创建简单的笔记存储应用,上一节课,我们完成了笔记的展示功能,本节课,我们来完成编辑功能. 编辑主要是两个功能:编辑现有的笔记以及创建新笔记.首 ...

  10. HTML5_路径

    <!DOCTYPE html> <hmtl> <html  lang="zh-cn"> <head> <meta charse ...