有了上次的八皇后的基础。这次准备解决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
//样例输入
//4
//1 0 1 1
//1 1 1 1
//1 1 1 1
//1 1 1 1
//样例输出
//0

先补充贴上八皇后第二种方法的代码:

感谢

@ Almost_Lover 

对代码的优化和注释,比之前更容易理解了

//参考程序二
#include <stdio.h>
int record[][]; // record记录全部解,共92种情况,每种情况都是长度为8的数串
int mark[]; // mark记录当前解,即当前8皇后在棋盘上的情况
int count = ; // 计数器,共92种
bool columnIsOk[], degree45IsOk[], degree135IsOk[]; // 分别记录列方向(上下方向),45度,135度方向上被控制的情况
void tryToPut(int row); // 声明递归函数,逐行尝试放置皇后,递归求得92种情况 int main() {
// 初始化棋盘,上下方向,45度方向,135度方向都未被控制
for(int i = ; i <=; i++)
columnIsOk[i] = true;
for(int i = ; i < ; i ++)
degree45IsOk[i] = degree135IsOk[i] = true; // 递归求解,获得全部可能情况
tryToPut(); int getResultNums; // 想要获得几种情况
int oneOfResults; // 总共92种情况中具体一种
scanf("%d", &getResultNums); // 按照输入,取出来结果
while(getResultNums --) {
scanf("%d", &oneOfResults);
for(int i = ; i <=; i++)
printf("%d", record[oneOfResults - ][i]);
printf("\n");
} return ;
} void tryToPut(int row) {
//如果最后一个皇后被放置完毕,将当前解复制到全部解中
if(row > ) {
for(int k = ; k < ; k ++)
record[count][k] = mark[k]; //因为要递归,所以count必须声明在函数外部
count ++;
} //在同一行上,逐一尝试将当前皇后放置在不同列上
for(int col=; col<=; col++) { // 递归结束条件:for循环8次,if条件都不满足,无法进入递归函数,递归结束,开始回溯
// 皇后所在的列坐标始终为 col
// 45度角坐标的'和'始终为 row+col
// 135度坐标的'和'始终为 row-col+9 (因为有可能出现负数,所以+9)
if(columnIsOk[col] && degree45IsOk [row + col] && degree135IsOk[row - col + ]) { // 能否放置皇后的条件,
mark[row] = col; // 放置皇后,mark数组对应的(row,col)坐标即一个皇后。这里将数组的(索引,值)抽象为坐标,值得学习。
columnIsOk[col] = degree45IsOk[row + col] = degree135IsOk[row - col + ] = false; // 控制三个方向
tryToPut(row + ); // 一行只能放一个皇后,所以下移一行,执行递归
// 其它代码都不重要,能把下面1行代码理解了就全部理解了
// 这一行存在的意义:递归结束,回溯遍历上一行
// 这就是递归,不是顺着来遍历的,而是倒着遍历的
columnIsOk[col] = degree45IsOk[row + col] = degree135IsOk[row - col + ] = true; // 撤销对3个方向的控制
} }
}

下面是我自己写的2n皇后的代码,不得不说看代码和写代码是两回事,看的时候觉得很好写,写起来各种出错,各种修改,最后缝缝补补,总算是通过了蓝桥杯的练习系统,

我用的是八皇后中第一种方法的扩展,虽然我写代码的时候思路很清晰,但写出来运行效率很低,运行时间长,以后还要改进,里面用的循环太多了,明天继续看看大神的答案再整理。

就是先下白棋和八皇后一个思路,然后每找到一个白棋的解 储存一下白棋解局,再重置棋盘(将黑棋子能下的地方全标为1)再下黑棋(和下白棋思路一样)每找到一个黑棋解或者循环完毕无解,就恢复白棋的棋局,继续回溯寻找白棋的解。

#include <iostream>
#include <cstdio>
using namespace std;
int count=;
int qipan[][],temp[][]; void fangheiqizi(int row,int n)//
{
if(row>=n)
{count++;
}
else{ for (int j=;j<n;j++)
if (qipan[row][j]==){
qipan[row][j]=-;
for (int k=row;k<n;k++)
for (int m=;m<n;m++)
if ((k==row||m==j||k+m==row+j||k-m==row-j)&&qipan[k][m]==)
qipan[k][m]=row+; fangheiqizi(row+,n); for (int k=row;k<n;k++)
for (int m=;m<n;m++)
if (qipan[k][m]==row+)
qipan[k][m]=;
qipan[row][j]=; }
} } void fangbaiqizi(int row,int n)//先放白棋,
{
if (row>=n){//每找到一个白棋的解储存下来 再重新布置棋局 再下黑棋 每找到一个黑棋的解或黑棋无解再恢复白棋的原来的局
for (int ii=;ii<n;ii++)
for (int jj=;jj<n;jj++)
{temp[ii][jj]=qipan[ii][jj];
if(qipan[ii][jj]!=-&&qipan[ii][jj]!=)qipan[ii][jj]=;
}
fangheiqizi(,n);
for (int ii=;ii<n;ii++)
for (int jj=;jj<n;jj++)
qipan[ii][jj]=temp[ii][jj]; }
else{ for (int j=;j<n;j++)
if (qipan[row][j]==){ qipan[row][j]=-;
for (int k=row;k<n;k++)
for (int m=;m<n;m++)
if ((k==row||m==j||(k+m==row+j)||(k-m==row-j))&&qipan[k][m]==)
qipan[k][m]=row+;
fangbaiqizi(row+,n);
// qipan[row][j]=1;
for (int k=row;k<n;k++)
for (int m=;m<n;m++)
if (qipan[k][m]==row+)
qipan[k][m]=;
qipan[row][j]=; } } }
int main()
{
int n;
cin>>n;
for (int i=;i<n;i++)
for (int j=;j<n;j++)
cin>>qipan[i][j];
fangbaiqizi(,n);
cout<<count; }

下面是大神答案。思路一样,方法可以看做八皇后中第三个方法的扩展,更简洁!不用考虑棋盘上的标记,只要额外两个数组来存储黑棋和白棋的解,判断点与点之间是否冲突就可以了

#include <cstdio>
#include<iostream>
using namespace std;
int chessb[][];//保存棋盘初始状态
int b[];//白皇后的放置位置 i行是第x列 b[i]=x;
int h[];//同上,不过是黑
int countn=;//计算方案数 int check(int queen[],int n)//判断同一列或者两对角线是否已经放置了
{
int i;
for (i = ; i < n; i++)
{
int judge=queen[i]-queen[n];
if(judge==||judge==i-n||judge==n-i)
{
return ;
}
}
return ; }
void bai(int line,int n)
{
int i;
if(line==n+)
{
countn++;
}
else
{
for(i=; i<=n; i++)
{
if(chessb[line][i]==&&i!=h[line])//可以放置
{
b[line]=i;
if(check(b,line))
{
bai(line+,n);
}
}
}
} } void hei(int line,int n)//黑皇后的搜索
{
int i;
if(line==n+) //黑皇后搜索完毕
{
bai(,n); //开始搜索白皇后
}
else
{
for(i=; i<=n; i++)
{
if(chessb[line][i]==)//可以放置
{
h[line]=i;
if(check(h,line))
{
hei(line+,n);
}
}
} }
} int main()
{
int n,i,j;
cin>>n;
for (i = ; i <= n; i++)
{
for (j = ; j <= n; j++)
{
scanf("%d",&chessb[i][j]);
}
}
hei(,n);
cout<<countn;
return ; ---------------------
作者:风卷云飞会天黑
来源:CSDN
原文:https://blog.csdn.net/castledrv/article/details/44203633
版权声明:本文为博主原创文章,转载请附上博文链接!

对八皇后的补充以及自己解决2n皇后问题代码的更多相关文章

  1. 计蒜课--2n皇后、n皇后的解法(一般操作hhh)

    给定一个 n*nn∗n 的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入 nn 个黑皇后和 nn个白皇后,使任意的两个黑皇后都不在同一行.同一列或同一条斜线(包括正负斜线)上,任意的两个白皇后都 ...

  2. 回溯法解决N皇后问题(以四皇后为例)

    以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...

  3. 多种解法解决n皇后问题

    多种解法解决n皇后问题 0x1 目的 ​ 深入掌握栈应用的算法和设计 0x2 内容 ​ 编写一个程序exp3-8.cpp求解n皇后问题. 0x3 问题描述 即在n×n的方格棋盘上,放置n个皇后,要求每 ...

  4. 回溯算法——解决n皇后问题

    所谓回溯(backtracking)是通过系统地搜索求解问题的方法.这种方法适用于类似于八皇后这样的问题:求得问题的一个解比较困难,但是检查一个棋局是否构成解很容易. 不多说,放上n皇后的回溯问题代码 ...

  5. javacpp-FFmpeg系列补充:FFmpeg解决avformat_find_stream_info检索时间过长问题

    javacpp-ffmpeg系列: javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片 javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转 ...

  6. 八皇后问题 2n皇后问题

    Description 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. 对于某 ...

  7. Unity 游戏框架搭建 2019 (二十七、二十八)弃用的代码警告解决&弃用的代码删除

    在前两篇,我们把所有的示例重头到尾整理了一遍. 当前的状态如下: 要做的事情: (完成) 备份:导出文件,并取一个合理的名字. 遗留问题: (完成) 第八个示例与之前的示例代码重复,功能重复. (完成 ...

  8. 完美解决pycharm 不显示代码提示问题

    pycharm 不显示代码提示 1.检查IDE省电模式是否关闭状态!!! file → power save mode 取消掉 2.检查代码提示是否成功开启. setting → Inspection ...

  9. 蓝桥杯试题 基础练习 2n皇后问题以及n皇后问题

    在学习2n皇后之前,我们应该认识一下n皇后问题: 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上.你的任务是,对于 ...

随机推荐

  1. uperTextView-从未如此惊艳!一个超级的TextView

    简介 下载:http://www.see-source.com/androidwidget/detail.html?wid=1273 欢迎使用SuperTextView,这篇文档将会向你展示如何使用这 ...

  2. 树状数组 || JZOI 1024. @szefany 的树

    题面:无 题解:无 代码: #include<cstdio> #include<cstring> #include<iostream> #include<al ...

  3. L1-016 查验身份证 (15 分)【考细心,考flag设置】

    一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8, ...

  4. 数学和物理太难?这些 GIF 让你秒懂抽象概念

    把科学带回家,给孩子最好的科学教育 觉得数学和物理很抽象很难懂吗?今天我们来分享一组数学和物理相关的动图,让你秒懂抽象概念. 数学动图 △ 从椭圆的一个焦点射出的光线总会通过另一个焦点. △ 真人版. ...

  5. 【C++】括号匹配

    #include<iostream> #include<cstring> #include<cstdlib> #include<queue> using ...

  6. 有几个PAT

    描述 字符串APPAPT中包含了两个单词“PAT”,其中第一个PAT是第2位(P),第4位(A),第6位(T):第二个PAT是第3位(P),第4位(A),第6位(T). 现给定字符串,问一共可以形成多 ...

  7. VisualStudioCode中用dotnet命令创建多个ASP.NET Core 项目、类库、控制台程序,并添加应用间的引用

    一.准备工作 首先安装VisualStudioCode并且可以使用. 1.首先新创建空的MyApps文件夹,作为项目主目录,下面将在这个文件夹中创建多个web应用程序.类型.控制台程序等. 2.打开V ...

  8. C# Asp.net中简单操作MongoDB数据库(一)

    需要引用MongoDB.Driver.dll.MongoDB.Driver.core.dll.MongoDB.Bson.dll三个dll. 1.数据库连接: public class MongoDb ...

  9. 6、jeecg 笔记之 自定义excel 模板导出(一)

    1.前言 jeecg 中已经自带 excel 的导出导出功能,其所使用的是 easypoi,尽管所导出的 excel 能满足大部分需求, 但总是有需要用到自定义 excel 导出模板,下文所用到的皆是 ...

  10. vue 封装组件

    props 接收数据 props对象里面 键值 是对改数据的 数据类型 的规定.做了规范,使用者就只能传输指定类型的数据,否则报警告 先根据要求写出完整的代码,再一一用参数实现组件封装 这里试着封装一 ...