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

这篇具有很好参考价值的文章主要介绍了N皇后问题(分支限界法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题描述:

在 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;//棋子所处的层数,也就是棋盘上的i
	vector<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;
}

代码运行截图:

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

 


 文章来源地址https://www.toymoban.com/news/detail-439514.html

到了这里,关于N皇后问题(分支限界法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单源最短路径问题——分支限界法(Java)

    1.1 分支限界法求解目标 分支限界法与回溯法的不同求解目标: 回溯法的求解目标:找出解空间树中满足约束条件的 所有解 ; 分支限界法的求解目标:找出满足约束条件的 一个解 ,或是在满足约束条件的解中找出使用某一目标函数值达到极大或极小的解,即在某种意义下

    2024年02月06日
    浏览(26)
  • 分支限界法解决0/1背包问题(C语言实现)

    分支限界法的基本思想 分支限界法的基本思想是,在分支结点上,预先分别估算沿着它的各个儿子结点向下搜索的路径中,目标函数可能取得的“界”,然后把这些儿子结点和它们可能所取得的“界”保存在一张结点表中,再根据题目要求选择表中“界”最大或最小的结点向

    2024年02月11日
    浏览(27)
  • 01背包问题三种解决(贪心动态规划分支限界)

    一、实验目的 1、深入理解背包相关问题。 2、能正确设计相应的算法,解决实际问题。   3、掌握算法时间复杂度分析。 二、实验要求 用3种方法求解0-1背包问题(贪心算法、 动态规划、分支限界法 ),获得精确最优解或近似最优解均可。 通过一个规模较大的实例比较不同

    2024年02月02日
    浏览(47)
  • 【算法】优先队列式分支限界法,以01背包问题为例

    题目链接:采药-洛谷 当洛谷上不让下载测试用例,可以试试:采药-ACWing 题目描述 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞

    2024年02月02日
    浏览(32)
  • 回溯法,分支限界法,动态规划法求解0-1背包问题(c++)

    问题描述 给定n种物品和一背包。物品i的重量是wi0,其价值为vi0,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 搜索空间: 子集树(完全二叉树) 约束函数(进包用): 如果当前背包中的物品总重量是cw,前面k-1件物品都已经决定是否进包,那

    2024年02月10日
    浏览(47)
  • 【算法】四、分支限界法

    分支限界法(Brach-and-Bound) 分支限界法与回溯法类似,也是在问题的解空间树上搜索问题的解,通过限界函数进行剪枝,但采用BFS广度优先策略搜索。 首先确定一个合理的限界函数,并根据限界函数确定目标函数的界[down,up];然后,按照广度优先策略搜索问题的解空间树:

    2024年02月04日
    浏览(27)
  • 06分支限界法

    分支限界法与回溯法的区别: (1) 求解目标不同 :回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。 (2) 搜索方式的不同 :回溯法以 深度优先

    2024年02月06日
    浏览(30)
  • 实验九 分支限界法

    任务描述 本关任务:编写用分支限界法。 相关知识 为了完成本关任务,你需要掌握:分支限界法。 实验原理 , , 印刷电路板将布线区域分成nm个方格。其中绿色的方格是封锁的,即不能布线的方格。白色的方格是可以布线的。精确的电路布线问题要求确定连接方格a中点到方

    2024年02月12日
    浏览(32)
  • 算法小课堂(九)分支限界法

    分支限界法是一种求解最优化问题的算法,常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。其基本思想是把问题的可行解展开,再由各个分支寻找最佳解。 在分支限界法中,分支是使用广度优先策略,依次生成扩展结点的所有分支。限界是在结点扩

    2024年02月06日
    浏览(26)
  • 01背包(动态规划,贪心算法,回溯法,分支限界法)

    有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? number=4,capacity=8 物品编号(i) W(体积) V(价值) 1 2 3 2 3 4 3 4 5 4 5 6 1.什么是动态规划 1.动态规划算法是通过拆分问题,定义问题状态和状态之间的关系, 使得

    2024年02月08日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包