对八皇后的补充以及自己解决2n皇后问题代码
有了上次的八皇后的基础。这次准备解决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
先补充贴上八皇后第二种方法的代码:
感谢
对代码的优化和注释,比之前更容易理解了
//参考程序二
#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皇后问题代码的更多相关文章
- 计蒜课--2n皇后、n皇后的解法(一般操作hhh)
给定一个 n*nn∗n 的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入 nn 个黑皇后和 nn个白皇后,使任意的两个黑皇后都不在同一行.同一列或同一条斜线(包括正负斜线)上,任意的两个白皇后都 ...
- 回溯法解决N皇后问题(以四皇后为例)
以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...
- 多种解法解决n皇后问题
多种解法解决n皇后问题 0x1 目的 深入掌握栈应用的算法和设计 0x2 内容 编写一个程序exp3-8.cpp求解n皇后问题. 0x3 问题描述 即在n×n的方格棋盘上,放置n个皇后,要求每 ...
- 回溯算法——解决n皇后问题
所谓回溯(backtracking)是通过系统地搜索求解问题的方法.这种方法适用于类似于八皇后这样的问题:求得问题的一个解比较困难,但是检查一个棋局是否构成解很容易. 不多说,放上n皇后的回溯问题代码 ...
- javacpp-FFmpeg系列补充:FFmpeg解决avformat_find_stream_info检索时间过长问题
javacpp-ffmpeg系列: javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片 javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转 ...
- 八皇后问题 2n皇后问题
Description 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. 对于某 ...
- Unity 游戏框架搭建 2019 (二十七、二十八)弃用的代码警告解决&弃用的代码删除
在前两篇,我们把所有的示例重头到尾整理了一遍. 当前的状态如下: 要做的事情: (完成) 备份:导出文件,并取一个合理的名字. 遗留问题: (完成) 第八个示例与之前的示例代码重复,功能重复. (完成 ...
- 完美解决pycharm 不显示代码提示问题
pycharm 不显示代码提示 1.检查IDE省电模式是否关闭状态!!! file → power save mode 取消掉 2.检查代码提示是否成功开启. setting → Inspection ...
- 蓝桥杯试题 基础练习 2n皇后问题以及n皇后问题
在学习2n皇后之前,我们应该认识一下n皇后问题: 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上.你的任务是,对于 ...
随机推荐
- 用TCP IP从C#实时传数据到Matlab
项目需要要从C#传实时数据到Matlab到数据分析,应该很多人也有这个需求,但是网上这方面的数据比较少,所以我把代码稍微贴下 首先是C#的部分 //介于我是同台电脑上传数据,直接用自己的IP建一个Se ...
- webpack 知识点
安装 webpack npm install -g webpack npm install -g webpack-cli@2.x 初始化项目 npm init -y npm install --sav ...
- Xamarin打包
- vue框架与koa2服务器实现跨域通信
首先我们在vue中引入axios, npm install axios --save 在需要用到的页面引入axios import axios from "axios"; 用axi ...
- loj2083 优秀的拆分 [NOI2016] SA
正解:SA 解题报告: 我永远喜欢loj! 显然$AABB$串相当于是由两个$AA$串拼起来的,所以可以先考虑如果求出来了所有$AA$串怎么求答案? 就假如能统计出$st[i]$表示所有以$i$为开头 ...
- ES6的字符串和数值的扩展
字符串扩展 对于处理大于两个字节(大于0xffff)的字符,let str =’\u{20bb7}abc’ ES5中的遍历 for(let i=0;i<str.length;i++){ con ...
- 记录请求的耗时(拦截器、过滤器、aspect)
文章前言 记录控制器请求的耗时处理通常有三种实现方式,分别是:过滤器.拦截器.aspect:下文将逐一实现. 1.Filter 过滤器 1.1.方法说明 需要实现 Filter 类,主要涉及三个方法: ...
- ORACLE——将多行文本数据转换成一行
前几天项目中有个到处文件的功能,但是有一个字段存进的数据存在换行情况,导出来的数据会出现错乱的情况,所以需要把换行的数据转换成一行.当然也可以在java程序中实现. 数据库中的数据为: SQL'; A ...
- redis----------linux和mac如何安装redis和启动,关闭
1.打开官网https://redis.io/download.官网有安装命令 2.以下是我的执行过程截图 执行完官网给的命令以后,再执行 make PREFIX=/usr/local/redis ...
- gRPC学习
概述 gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法, ...