N皇后问题(分支限界法)
创始人
2024-03-19 04:29:39

问题描述:

在 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;//棋子所处的层数,也就是棋盘上的ivectorx;//保存该棋子以及在它之前的棋子所在的列数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
using namespace std;//定义一个节点类
struct Node{int number;vectorx;//保存当前解 
}; //定义一个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(){queueQ;//活节点队列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<>N;nQueen(N);return 0;
}

代码运行截图:

 

 


 

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...