N皇后问题(分支限界法)

article/2025/10/6 0:58:26

问题描述:

在 n * n 格的棋盘上放置彼此不受攻击的 n 个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题等价于在 n * n 的棋盘上放置 n 个皇后,任何 2个皇后不放在同一行或同一列或同一斜线上。

设计一个解 n 皇后问题的队列式分支限界法,计算在 n * n 个方格上放置彼此不受攻击的 n 个皇后的一个放置方案。

数据输入:

第一行有1个正整数 n 。

结果输出:

第一行是n个皇后的放置方案。

思路:

1.题目分析:

对于每一个放置点而言,它需要考虑四个方向上是否已经存在皇后。分别是行、列,45度斜线和135度斜线。

行:每一行只放一个皇后,直到我们把最后一个皇后放到最后一行的合适位置,则算法结束。

列:列相同的约束条件,只需判断 j 是否相等即可。

45度斜线和135度斜线:约束条件——当前棋子和已放置好的棋子不能存在行数差的绝对值等于列数差的绝对值的情况,若存在则说明两个棋子在同一条斜线上

2.算法选择:

用分支限界法来解决 n 皇后问题。对于该问题它满足两种树(子集树、排列树)结构。这里由于每一个合适的放置点出现最优解的概率是相等的,因此不需要使用优先队列。stl 提供了一个已经封装好的队列queue。

A.子集树。我们把行约束条件和其它约束条件放在一起,即认为每一行,棋子都有n个位置可以放置。于是它的空间结构如下:

 

(假设n = 3,这个图只画出了两层)

B.排列树。我们把行约束条件单独拿出来,也就是我们认为总共有八个皇后,这八个皇后必须都要放上去,但是放的位置不同,显然这是一个排列树。于是它的空间结构如下:

 

3.算法设计

1).数据存储

对于每一个棋子节点,它需要储存两个信息,一个是该棋子所处的层数,另一个就是这个棋子它是由哪些棋子扩展而来的,也就是它的路径。

//定义一个节点类
struct Node{int number;//棋子所处的层数,也就是棋盘上的ivector<int>x;//保存该棋子以及在它之前的棋子所在的列数j。也就是它的所有父辈节点的信息 
}; 

 比如图中的节点 m ,它储存的信息就是number = 3,x[1]=  1;x[2] = 2;x[3] = 3。指明了前面棋子的列信息。

2).定义一个Queen的类,封装一些相关的信息,比如皇后个数和最优解的数组

class Queen{friend int nQueen(int);public:bool Place(Node q,int n);void Research();int n;//皇后个数int *bestx;//最优解
};

4.细节处理

1).当前所处层数的判断:每一层的结尾都压入一个 number =  -1 的节点,每一次在取出队列中的节点时进行判断如果该节点的 number = -1,那么当前层数 t 加 1,并且再压入一个 number = -1的节点。然后重新往队列取出下一个节点。

2).算法终止条件:如果当前取出的节点 number == n,表明已经处理到最后一层了,并且最后一层满足约束条件的棋子位置已经都存在队列中了。这时我们把当前节点的数组 x 赋值给 bestx ,然后结束算法。

Code:

#include<bits/stdc++.h>
using namespace std;//定义一个节点类
struct Node{int number;vector<int>x;//保存当前解 
}; //定义一个Queen的类 
class Queen{friend int nQueen(int);public:bool Place(Node q,int n);void Research();int n;//皇后个数int *bestx;//最优解
}; //判断是否能够放置的函数 
bool Queen::Place(Node q,int n){for(int j = 1;j < n;j ++ )if((abs(n-j) == abs(q.x[j] - q.x[n])) || (q.x[j] == q.x[n])) return false;return true;
}void Queen::Research(){queue<Node>Q;//活节点队列Node sign;sign.number = -1;Q.push(sign);//同层节点尾部标志int t = 1;//当前节点所处的层Node Ew;//当前扩展节点 Ew.number = 0; //搜索子集空间树while(1){	//检查所有的孩子节点 for(int k = 1;k <= n;k ++ ){//把当前扩展节点的值赋给下一个节点 Node q;q.number = t; q.x.push_back(0);//第一个位置为0 for(int i = 1;i < t;i ++ ) q.x.push_back(Ew.x[i]);q.x.push_back(k);if(Place(q,t))Q.push(q);}	 //取下一扩展节点,取出,赋值给Ew Ew = Q.front();Q.pop();if(Ew.number == -1){//同层节点尾部标记t ++ ;//进入下一层 Q.push(sign);//增加标记//继续往下去下一个节点 Ew = Q.front();Q.pop();}		if(Ew.number == n){//找到最后一层的节点 for(int i = 0;i <= n;i ++ ) bestx[i] = Ew.x[i];break;} }
}int nQueen(int n){Queen X;X.n = n;	X.bestx = new int[n+1];for(int i = 0;i <= n;i ++ ) X.bestx[i] = 0;X.Research();for(int i = 1;i <= n;i ++ ) cout<<X.bestx[i]<<" ";
}int main(){	int N;cin>>N;nQueen(N);return 0;
}

代码运行截图:

 

 


 


http://chatgpt.dhexx.cn/article/wQQT0k8F.shtml

相关文章

N皇后问题详解

文章目录 一、题目描述二、题目解析&#xff08;1&#xff09;思考一(集合回溯)&#xff08;2&#xff09;思考二(数组深度递归)&#xff08;3&#xff09;思考三(位运算) 一、题目描述 N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后&#xff0c; 要求&#xff1a;任何两个皇…

3.2 回溯法—N皇后问题

1. 问题描述 在 n n n\times n nn的棋盘上摆放 n n n个皇后&#xff0c;使任意两个皇后都不能处于同一行、同一列或同一斜线上 2. 问题分析 下以求解4皇后问题为例&#xff0c;分析4皇后问题的排列树以及回溯过程&#xff1a; 搜索及回溯过程&#xff1a; 解空间树&#…

【经典算法】N皇后问题

✨前言✨ N皇后问题经典的解决方案是暴力递归&#xff0c;其时间复杂度是O(2^n),因此常用来测试计算机的算力。今天我会给大家带来经典方法的详解&#xff0c;也会给大家展示N皇后优化后的大神解法。做一道经典题目&#xff0c;来一场思维旅行。 目录 ✨前言✨ &#x1f4a1;…

n皇后问题(回溯法)(超易理解)(详细注释)

问题&#xff1a; N皇后问题是一个经典的问题&#xff0c;描述如下&#xff1a; 在的方格棋盘需要放置N个皇后&#xff0c;使得它们不相互攻击&#xff0c; 即任意2个皇后不允许处在同一排&#xff0c;同一列&#xff0c;也不允许处在与棋盘边框成45度角的斜线上。 对于给定的N…

n皇后问题(回溯法)

目录 1.问题描述 2.问题分析 3.完整源码 1.问题描述 八皇后问题是十九世纪著名的数学家高斯于1850年提出的。问题是:在88的棋盘上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上。可以把八皇后问题扩展到n皇后问…

【浏览器跨域】跨域访问接口浏览器怎么设置?

window系统 1、右键浏览器&#xff0c;点击属性 2、找到目标&#xff0c;目标输入框内容最后面加上 --disable-web-security --user-data-dirC:\MyChromeDevUserData&#xff0c;–user-data-dir 3、点击确定 4、重新打开浏览器即可 mac系统 终端输入&#xff0c;重新打开浏…

AJAX跨域访问(不同域之间相互访问)

目录 一、跨域&#xff1a;二、同源策略&#xff1a;三、解决Ajax跨域问题的方案&#xff1a;方案一&#xff1a;设置响应头方案二&#xff1a;jsonp方案三&#xff1a;jQuery封装jsonp方案四&#xff1a;代理机制&#xff08;httpclient&#xff09;方案五&#xff1a;nginx反…

nginx配置图片跨域访问

在server段中添加红框内的图片跨域内容 参数 location ~* .*.(gif|jpg|jpeg|png|bmp|swf)$ { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS…

浏览器跨域访问限制

一.什么是跨域 广义的跨域&#xff1a; (1) 资源跳转&#xff1a;A链接、重定向、表单提交 (2) 资源嵌入&#xff1a;<link>、<script>、<img>、<frame>等dom标签&#xff0c;还有样式中background:url()、font-face()等文件外链 (3) 脚本请求&#x…

Django 多方式实现跨域访问

一、什么是跨域 1.1 跨越介绍 跨域&#xff0c;是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的&#xff0c;是浏览器对JavaScript实施的安全限制。 这里说明一下&#xff0c;无法跨域是浏览器对于用户安全的考虑&#xff0c;如果自己写个没有同源策略的浏览…

Flask中跨域访问的实现

在我们访问不同的服务器时&#xff0c;就会涉及到了跨域的问题。因为不同域名之间是无法进行交流的&#xff0c;然后跨域就打破了这种规则的限制。说起Flask中的跨域&#xff0c;就不得不提到CORS组件了&#xff0c;相信大家在其它框架中也见过了它的身影。下面我们就跨域问题和…

Tomcat设置允许跨域访问

开发React项目时前端通过axios向后端代码发起请求调试的时候由于后端代码运行在8080端口而React项目运行在3000端口导致浏览器的同源策略禁止跨域请求&#xff0c;因此需修改Tomcat配置文件web.xml以开放跨域访问。 在tomcat的web.xml文件末尾加上&#xff1a; <filter>…

express 允许跨域访问

设置Express const express require(express) const bodyParser require(body-parser)const app express() // 处理参数 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));// 设置允许跨域访问该服务 app.all(*, function (req, res, nex…

tomcat 设置允许跨域访问

既然想到使用tomcat进行跨域的设置&#xff0c;而不使用在项目中设置header来解决&#xff0c;说明你也是tomcat 下的资源需要做跨域处理吧&#xff1f;这也是一个统一的允许跨域设置&#xff0c;tomcat下的所有请求都将放开&#xff0c;请注意。 具体步骤&#xff1a; 1.首先…

Chrome浏览器 设置跨域访问

由于浏览器的安全策略&#xff0c;不同域名的访问会被限制&#xff0c;导致不能访问 chorme或者360都可以使用下列设置来解决这个问题&#xff1a; &#xff08;1&#xff09;在电脑上新建一个目录&#xff0c;例如&#xff1a;C:\MyChromeEnvUserData &#xff08;2&#x…

tomcat9配置允许跨域访问

目录 一、问题描述二、解决办法三、程序截图 一、问题描述 最近在用Tomcat9最新版本部署程序的时候&#xff0c;发现其他服务访问我的静态资源的时候出现了跨域访问&#xff0c;结果很明显被拦截了&#xff0c;之前的文章介绍了Tomcat8.5的跨域配置&#xff0c;但是研究发现&a…

html的页面怎样直接跨域访问,【HTML】iframe跨域访问问题

概述 本地同一浏览器访问本地HTML文件和访问服务器端HTML文件,本地Iframe没有自适应高度,而服务器端的Ifrane自适应了高度。 1.问题重现: Chrome 版本 41.0.2272.101 (64-bit) OS:Win8.1 Chrome访问服务器端HTML文件呈现的结果 Chrome访问本地HTML文件呈现的结果 本地访问的…

vue跨域访问

vue跨域访问的问题&#xff08;基于允许跨域访问的前提&#xff09; 找到“ vue.config.js"&#xff0c;有些不是vue.config.js命名&#xff0c;也就是找到重写路径的js文件。重写一下自己要替换的路径&#xff0c;在原有基础上加一个 新建一个dev.js文件内容如下&#…

关于跨域访问

1 概念 2 案例 3 解决 4 实现 5 什么是跨域问题 示意图 1 概念 跨域访问&#xff0c;是指从一个域名的网页去请求另一个域名的资源。比如从 www.baidu.com 页面去请求 ww w.google.com 的资源。 但是一般情况下不能这么做跨域访问&#xff0c;因为有浏览器的 “ 同源策略…

什么是跨域?如何实现跨域访问?

跨域是指不同域名之间相互访问。 JavaScript同源策略的限制&#xff0c;A域名下的JavaScript无法操作B或是C域名下的对象 实现&#xff1a; 1、JSONP跨域&#xff1a;利用script脚本允许引用不同域下的js实现的&#xff0c;将回调方法带入服务器&#xff0c;返回结果时回调 2、…