对八皇后的补充以及自己解决2n皇后问题代码

时间:2022-03-02 12:44:24

有了上次的八皇后的基础。这次准备解决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&lowbar;find&lowbar;stream&lowbar;info检索时间过长问题

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

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

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

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

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

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

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

  9. 【技术贴】解决myeclipse SVN 提交代码 commit&colon;remains in tree-conflict错误的解决办法

    [技术贴]解决myeclipse SVN 提交代码 commit:remains in tree-conflict错误的解决办法 错误是:Aborting commit: xxxxx’ remains ...

随机推荐

  1. Got the Best Employee of the year 2015 Star Award

    Got "The Best Employee of the year 2015 Star Award" from the company, thanks to all that h ...

  2. C&plus;&plus;的那些事:函数全解析

    一.函数的结构 函数在C++中可能出现在三种地方,一是函数的定义,它包括了如上图的结构:二是函数的声明,它与函数的定义相比,没有了函数体部分:三则是函数的调用.当然,不同的函数定义可以还会稍有不同,比 ...

  3. VI 配置文件(略全)

    配置 ~/.vimrc文件. root则放到/etc/vimrc 具体详见代码 "====================================================== ...

  4. 笔记整理——Linux下C语言正则表达式

    Linux下C语言正则表达式使用详解 - Google Chrome (2013/5/2 16:40:37) Linux下C语言正则表达式使用详解 2012年6月6日Neal627 views发表评论 ...

  5. jQuery控制a标签不可点击 不跳转

    jquery禁用a标签方法1 01 02 03 04 05 06 07 08 09 10 11 12 $(document).ready(function () {         $("a ...

  6. CSS 设置table下tbody滚动条

    table tbody { display:block; height:195px; overflow-y:scroll; } table thead, tbody tr { display:tabl ...

  7. day 7-13 数据库的数据类型

    一. 数据类型 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 注意:int类型的宽度是显示宽度,并非是数据的存储宽度 详细的介绍:http:// ...

  8. JSP页面用&lt&semi;a&gt&semi;标签访问 Action 出错

    问题: JSP页面 <a href="/crud1/crud1/add.action" >添加</a> struts.xml 中: <package ...

  9. Stanford CS231n - Convolutional Neural Networks for Visual Recognition

    网易云课堂上有汉化的视频:http://study.163.com/course/courseLearn.htm?courseId=1003223001#/learn/video?lessonId=1 ...

  10. 辅助测试工具xip&period;io

    http://xip.io/ https://github.com/basecamp/xip-pdns