N后问题
n皇后问题实验报告

n皇后问题实验报告n皇后问题实验报告引言:n皇后问题是一个经典的数学问题,它要求在一个n×n的棋盘上放置n个皇后,使得它们互相之间不能相互攻击,即任意两个皇后不能处于同一行、同一列或同一对角线上。
本实验旨在通过编程实现n皇后问题的求解,并探索不同算法在解决该问题上的性能差异。
实验步骤及结果:1. 回溯算法的实现与性能分析回溯算法是最常见的解决n皇后问题的方法之一。
它通过递归的方式遍历所有可能的解,并通过剪枝操作来提高效率。
我们首先实现了回溯算法,并对不同规模的问题进行了求解。
在测试中,我们将问题规模设置为4、8、12和16。
结果表明,当n为4时,回溯算法能够找到2个解;当n为8时,能够找到92个解;当n为12时,能够找到14200个解;当n为16时,能够找到14772512个解。
可以看出,随着问题规模的增加,回溯算法的求解时间呈指数级增长。
2. 启发式算法的实现与性能分析为了提高求解效率,我们尝试了一种基于启发式算法的解决方法。
在该方法中,我们使用了遗传算法来搜索解空间。
遗传算法是一种模拟生物进化过程的优化算法,通过进化操作(如选择、交叉和变异)来寻找问题的最优解。
我们将遗传算法应用于n皇后问题,并对不同规模的问题进行了求解。
在测试中,我们将问题规模设置为8、12和16。
结果表明,遗传算法能够在较短的时间内找到问题的一个解。
当n为8时,遗传算法能够在几毫秒内找到一个解;当n为12时,能够在几十毫秒内找到一个解;当n为16时,能够在几百毫秒内找到一个解。
相比之下,回溯算法在同样规模的问题上需要几秒钟甚至更长的时间。
3. 算法性能对比与分析通过对比回溯算法和启发式算法的性能,我们可以看到启发式算法在求解n皇后问题上具有明显的优势。
回溯算法的求解时间随问题规模呈指数级增长,而启发式算法的求解时间相对较短。
这是因为启发式算法通过优化搜索策略,能够更快地找到问题的解。
然而,启发式算法并非没有缺点。
n皇后问题递归算法

n皇后问题递归算法想象一下,有一个棋盘,上面要放下几个皇后。
这个皇后可不是普通的角色,她可厉害了,能横着、竖着、斜着攻击其他棋子。
没错,皇后就是这么霸道,咱们要确保她们互不干扰。
这个事情听起来有点棘手,但其实只要动动脑筋,找到一些聪明的方式,问题就迎刃而解了。
说到这里,很多小伙伴可能会想:“这不是简单的下棋吗?有什么难的?”可是,等你真正上手的时候,嘿嘿,才发现事情并没有想象中那么简单。
我们从一个小小的例子开始吧。
假如棋盘是个4×4的小方块,咱们的目标就是在这个方块上放四个皇后。
听起来简单吧?但试想一下,放下第一个皇后没问题,她随便摆哪儿都行,棋盘上空荡荡的。
但是当你放下第二个皇后时,哎哟,她可就要考虑第一位皇后的地盘了,不能让她们互相看对方的脸呀。
接下来再放第三个、第四个,感觉压力山大,像是要参加一场马拉松比赛,刚开始风驰电掣,后来就感觉体力不支,越往后越是踌躇满志又心慌慌。
于是,咱们决定采用递归的方式来解决这个问题。
你说,递归是什么鬼?其实就是一种方法,简单点说就是“自己叫自己”。
我们可以从放第一个皇后开始,然后把剩下的事情交给下一个步骤,就像是把作业一层一层递交给老师,直到所有问题都解决为止。
我们可以把当前棋盘的每一行都视为一个新的阶段,逐行逐列地放置皇后。
如果这一步走不通,那就“咱们重来”。
这就像是人生中的很多事情,不顺利的时候就换个思路,继续前进。
当你把第一行的皇后放好,接下来就要检查第二行的每一个位置,看看哪里可以放。
每检查一个位置,就像是在打探敌情,谨慎又小心。
噢,不行,这个位置被第一行的皇后盯上了,得换个地方。
这样一来,你可能会发现,有的地方放不下,有的地方则一片大好,任你选择。
一直检查到棋盘的最后一行,如果成功放下皇后,哇,心里那种成就感,简直像中了大奖一样!可是如果发现放不下,那就要退回去,换个方案,哪怕是从头再来。
这就是递归的魅力,既简单又复杂,似乎在和我们的人生进行一场心灵的对话。
oeisn皇后问题数学解法

oeisn皇后问题数学解法OEISN皇后问题OEISN皇后问题即为在一个n*n的棋盘上放置n个皇后,使得每行、每列和每条对角线上只有一个皇后,求解最优解。
概述OEISN皇后问题,是经典的NP完全问题,这意味着,在多项式时间内无法求出此问题的最优解。
目前已知求解该问题的最好算法是基于backtrack的算法,通过枚举所有的情况,寻找满足条件的最优解。
解法步骤下面将介绍一种基于回溯法的OEISN皇后问题的解法。
1. 生成初始状态首先,生成一个初始状态,即在每一行中随机选择一个位置放置一个皇后。
2. 迭代搜索接下来,进行迭代搜索。
从第一行开始,依次在每一行中选择一个位置来放置皇后。
如果放置的皇后不满足条件,则尝试在该行中选择其他位置放置。
如果在该行中的所有位置都不能放置皇后,那么回溯到上一行重新选择位置。
3. 结束条件在每一行都完成放置皇后的任务后,判断当前解是否满足条件。
如果满足条件,统计解的数量,并返回上一行。
否则,回溯到上一行,重新选择位置。
4. 输出解在整个搜索过程结束后,输出所有找到的最优解,并统计总解的数量。
优缺点与其他的NP完全问题相比,OEISN皇后问题通过backtrack算法进行求解,相对来说解法较为简单。
但是,也存在其缺点。
由于该问题是基于穷举法的搜索,需要枚举所有情况,所以对于大规模的问题,该算法存在时间复杂度高的问题。
实例解释下面,我们以n=4的情况为例,来解释该算法的求解过程。
初始状态:在这个初始状态下,我们依次枚举每一行下的位置。
首先,选择在第一行的第一个位置下放置皇后。
由于第二行的任何位置都不能与第一行的皇后不共线,所以,在第二行的第三个位置放置皇后。
在第三行中,第一和第四个位置与已经放置的皇后不共线,所以这里我们选择第一列放置皇后。
在最后一行中,只有第一列能满足要求。
统计到此时,我们已经找到了一个最优解。
不难发现,该算法从第一行到第四行依次枚举每一个位置,由于对于每一行我们都进行了全面的搜索,所以我们可以保证找到的最优解一定是全局最优解。
N皇后问题及答案解

N皇后问题及答案解题⽬在⼀张N∗N的国际象棋棋盘上,放置N个皇后,使得所有皇后都⽆法互相直接攻击得到,(皇后可以直接攻击到她所在的横⾏,竖列,斜⽅向上的棋⼦),现在输⼊⼀个整数N,表⽰在N∗N的棋盘上放N个皇后,请输出共有多少种使得所有皇后都⽆法互相直接攻击得到的⽅案数。
例如下⾯这样的摆法,是4皇后的⼀个解 (1代表有皇后,0代表没有)0 1 0 00 0 0 11 0 0 00 0 1 0输⼊⼀个整数N,代表皇后的个数输出输出⽅案数样例输⼊样例输⼊14样例输⼊28样例输出样例输出12样例输出292⼀、DFS+回溯(1)设已经放好的皇后坐标为(i,j),待放⼊的皇后坐标为(r,c),则它们满⾜以下关系:(1)不同⾏,即 i ≠ r;(2)不同列,即 j ≠ c;(3)不在斜对⾓线上,即 |i-r| ≠ |j-c|.可以在⼀⾏逐列尝试,这样就不⽤考虑(1)了。
#include <iostream>#include <algorithm>#include <cstring>using namespace std;int n, tot = 0;int col[15] = {0}, ans[15] = {0}; //col[i]的值为第i⾏的皇后的列数的值,即j,ans[]数组⽤来存放结果bool check(int c, int r) //检查是否和已经放好的皇后冲突{for (int i = 0; i < r; i++)if (col[i] == c || (abs(col[i] - c) == abs(i - r))) //因为是逐⾏放置,所以只考虑纵向和斜向return false;return true;}void dfs(int r,int m) //在第r⾏放皇后,m表⽰⾏数{if(r==m){ //r==m,即皇后放到最后⼀⾏,满⾜条件,tot++,返回;tot++;return;}for(int c=0;c<m;c++) //在此⾏逐列尝试if(check(c,r)){ //检查是否冲突col[r]=c; //不冲突就在此列放皇后dfs(r+1,m); //转到下⼀⾏继续尝试}}int main(){cin>>n;for (int i = 0; i <= 13; i++) //算出所有N皇后的答案,先打表,不然会超时{memset(col, 0, sizeof(col)); //清空col,准备计算下⼀个N皇后问题tot = 0;dfs(0,i);ans[i] = tot;}cout << ans[n] << endl;return 0;}在上述程序中,dfs()⼀⾏⾏放置皇后,时间复杂度为O(N!);check()判断冲突,时间复杂度为O(N),总的为O(N*N!)!⾮常的⾼。
n皇后问题递归算法c语言

n皇后问题递归算法c语言概述n皇后问题是一个经典的回溯算法问题,它要求在一个n×n的棋盘上放置n个皇后,使得它们互不攻击。
本文将使用递归算法来解决n皇后问题,并使用C语言进行实现。
问题描述在n×n的棋盘上放置n个皇后,使得它们不在同一行、同一列或同一斜线上。
其中,皇后的移动规则是可以横向、纵向、对角线方向上自由移动任意步数。
算法思路为了解决n皇后问题,我们可以采用递归的方式逐行放置皇后。
具体地,可以按照行优先的顺序,从第一行开始放置皇后,并逐行向下递归,直到放置了n个皇后,或者无法再放置皇后为止。
算法的关键在于如何判断当前位置是否可以放置皇后,即判断是否与已经放置的皇后位置冲突。
为了判断冲突,我们需要考虑以下几个方面:1.所有皇后不能在同一列:我们可以使用一个数组q ue en[]来记录每一行放置的皇后的列位置。
2.所有皇后不能在同一对角线上:我们可以使用两个数组up D ia g[]和d ow nD ia g[]来记录每一条对角线上是否已经存在皇后。
对于任意一个位置(i,j),它所在的主对角线上的元素满足i-j的值相等,次对角线上的元素满足i+j的值相等。
在放置皇后时,我们可以逐个尝试每一列,然后检查当前位置是否与已经放置的皇后位置冲突,如果冲突则继续尝试下一列,直到找到一个合适的位置。
然后,继续递归放置下一行的皇后,直到放置了n个皇后或者无法再放置为止。
伪代码定义一个全局整型数组q ue en[],用于记录每一行放置的皇后的列位置定义两个全局整型数组u pD ia g[]和do wn D ia g[],用于记录每一条对角线上是否已经存在皇后P r oc ed ur en Qu ee ns(r ow):i f ro w=n://找到一个解P r in tS ol ut io n()r e tu rnf o rc ol fr om0t on-1:i f Ca nP la ce Qu ee n(r o w,co l):P l ac eQ ue en(r ow,co l)n Q ue en s(ro w+1)R e mo ve Qu ee n(ro w,c o l)P r oc ed ur eC an Pl ace Q ue en(r ow,c ol):i f qu ee n[co l]!=-1:r e tu rn fa ls ei f up Di ag[r ow-c ol+n-1]!=-1o rd ow nDi a g[ro w+co l]!=-1:r e tu rn fa ls er e tu rn tr ueP r oc ed ur eP la ce Que e n(ro w,co l):q u ee n[co l]=r owu p Di ag[r ow-c ol+n-1]=1d o wn Di ag[r ow+c ol]=1q u ee n[co l]=-1u p Di ag[r ow-c ol+n-1]=-1d o wn Di ag[r ow+c ol]=-1P r oc ed u r eP ri nt Sol u ti on():f o rr ow fr om0t on-1:f o rc ol fr om0t on-1:i f qu ee n[co l]=r ow:p r in t"Q"e l se:p r in t"*"p r in tn ew li nep r in tn ew li neC语言实现下面是使用C语言实现的n皇后问题递归算法的代码示例:#i nc lu de<s td io.h>#d ef in eN8i n tq ue en[N];//记录每一行放置的皇后的列位置i n tu pD ia g[2*N-1];//记录每一条对角线上是否已经存在皇后i n td ow nD ia g[2*N-1];//记录每一条对角线上是否已经存在皇后v o id nQ ue en s(in tro w);i n tc an Pl ac eQ ue en(i nt ro w,in tc ol);v o id pl ac eQ ue en(in t ro w,in tc ol);v o id pr in tS ol ut ion();i n tm ai n(){f o r(in ti=0;i<N;i++){q u ee n[i]=-1;}f o r(in ti=0;i<2*N-1;i++){u p Di ag[i]=-1;d o wn Di ag[i]=-1;}n Q ue en s(0);r e tu rn0;}v o id nQ ue en s(in tro w){i f(r ow==N){p r in tS ol ut io n();r e tu rn;}f o r(in tc ol=0;c ol<N;c ol++){ i f(c an Pl ac eQ ue en(r ow,c ol)){ p l ac eQ ue en(r ow,co l);n Q ue en s(ro w+1);r e mo ve Qu ee n(ro w,c o l);}}}i n tc an Pl ac eQ ue en(i nt r o w,in tc ol){i f(q ue en[c ol]!=-1){r e tu rn0;}i f(u pD ia g[ro w-col+N-1]!=-1||do wnD i ag[r ow+c ol]!=-1){ r e tu rn0;}r e tu rn1;}v o id pl ac eQ ue en(in t ro w,in tc ol){q u ee n[co l]=r ow;u p Di ag[r ow-c ol+N-1]=1;d o wn Di ag[r ow+c ol]=1;}v o id re mo ve Qu ee n(i n tr ow,i nt co l){q u ee n[co l]=-1;u p Di ag[r ow-c ol+N-1]=-1;d o wn Di ag[r ow+c ol]=-1;}v o id pr in tS ol ut ion(){f o r(in tr ow=0;r ow<N;r ow++){f o r(in tc ol=0;c ol<N;c ol++){i f(q ue en[c ol]==ro w){p r in tf("Q");}e ls e{p r in tf("*");}}p r in tf("\n");}p r in tf("\n");}总结本文使用C语言实现了n皇后问题的递归算法。
n皇后问题

n 后问题1 问题描述:N 皇后问题是一个古老而著名的问题。
该问题是十九世纪著名的数学家高斯1850年提出的。
八皇后问题要求在一个N *N 的棋盘上放上N 个皇后,使得每一个皇后既攻击不到另外N-1个皇后,也不被另外N-1个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子,问有多少种不同的摆法?并找出所有的摆法。
因此,N 皇后问题等于要求N 个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
2 回朔法回溯法有“通用的题解法”之称。
从问题的某种可能情况出发,搜索所有能到达的可能情况,然后以其中一种可能的情况为新的出发点,继续向下探索,当所有可能情况1 2 3 4 5 6 7 8 1 2 3 4 5 6 78都探索过且都无法到达目标的时候,再回退到上一个出发点,继续探索另一个可能情况,这种不断回头寻找目标的方法称为“回溯法”。
适用于解组合是较大的问题。
回朔法思想:1针对所给问题,定义问题的解空间。
2.确定易于搜索的解空间结构。
3.以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。
在搜索过程中,通常采用两种策略避免无效搜索:一是用约束函数剪去得不到可行解的子树;二是用限界函数剪去得不到最优解的子树。
这两类函数统称为剪枝函数。
回溯算法的一个显著的特性是在搜索过程中动态产生问题的解空间。
在任何时刻,只保存从根结点到当前扩展结点的路径。
因此,回溯算法的空间需求为o(n),(n为从根结点起最长路径的长度)。
而显式地存储整个解空间则需要o(2n)或o(n!)内存空间。
回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法。
void backtrack (int t){if (t>n) output(x);elsefor (int i=f(n,t);i<=g(n,t);i++){x[t]=h(i);if (constraint(t)&&bound(t)) backtrack(t+1);}}采用树的非递归深度优先遍历算法,可将回溯法表示为一个非递归迭代过程。
n后问题-回溯法
n后问题-回溯法问题描述: 在n*n的棋盘上放置彼此不受攻击的n个皇后。
按国际象棋的规则,皇后可以与之处在同⼀⾏或者同⼀列或同⼀斜线上的棋⼦。
n后问题等价于在n*n格的棋盘上放置n皇后,任何2个皇后不放在同⼀⾏或同⼀列的斜线上。
算法设计: |i-k|=|j-l|成⽴,就说明2个皇后在同⼀条斜线上。
可以设计⼀个place函数,测试是否满⾜这个条件。
1 当i>n时,算法搜索⾄叶节点,得到⼀个新的n皇后互不攻击放置⽅案,当前已找到的可⾏⽅案sum加1. 2 当i<=n时,当前扩展结点Z是解空间中的内部结点。
该结点有x[i]=1,2,3....n共n个⼉⼦节点。
对当前扩展结点Z的每个⼉⼦节点,由place检察其可⾏性。
并以深度优先的⽅式递归地对可⾏⼦树,或剪去不可⾏⼦树。
算法描述: #include <iostream>#include <cstdlib>using namespace std;class Queen{friend int nQueen(int);private:bool Place(int k);void Backtrack(int t);int n,* x;long sum;};bool Queen::Place(int k){for(int j=1;j<k;j++)if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))return false;return true;}void Queen::Backtrack(int t){if(t>n)sum++;elsefor(int i=1;i<=n;i++){x[t] = i;if(Place(t))Backtrack(t+1);}}int nQueen(int n){Queen X;X.n = n;X.sum = 0;int *p = new int [n+1];for(int i=0;i<=n;i++)p[i] = 0;X.x = p;X.Backtrack(1);delete [] p;cout<<X.sum<<endl;return X.sum;}int main(){nQueen(4);nQueen(2);nQueen(3);return0;}执⾏结果:迭代回溯:数组x记录了解空间树中从根到当前扩展结点的路径,这些信息已包含了回溯法在回溯时所需要的信息。
第五章 回溯法1--基本概念--n后问题
B
3 4
C
4 G G 3 M M 2 H H 4 N N
D D
4 26>25 2 I I 3 P P 2 J J
E
3
图1 四个顶点的带权图
F
4 L L 59
K
2 Q Q
O
60+6>59 25
第五章 回溯法
19+6=25 29+30>25
活结点 当前扩展结点 死结点 D B 1 A
0 1 F 0
K
45
1
0
E
C 0 G 0 1 N
25
死结点 1
1
H
0
I
1
J
0 O
0
4
L
50
M
25
图5-2 在0-1背包问题的解空间树上搜索最优解
第五章 回溯法
例2:旅行售货员问题:某售货员要到若干城市推销商 品,已知各城市间的路程(或旅费)。他要选一条从 驻地出发,经过每个城市一遍,最后回到驻地的路线 使总的路程(总的旅费)最小。
第五章 回溯法 2
2. 解空间树
通常把解空间组织成解空间树。 例如:对于n=3时的0-1背包问题,其解空间用一 棵完全二叉树表示,如下图所示。
1
A
0
B
1 0 1
C
0
D 1 H
0 1
E
0
F
1 0 1
G
0
I
J
K
L
M
N
O
0-1背包问题的解空间树
第五章 回溯法
3
3. 搜索解空间树的过程
八皇后问题(N皇后问题)
⼋皇后问题(N皇后问题)⼋皇后问题,是⼀个古⽼⽽著名的问题,是回溯算法的典型案例。
该问题是国际西洋棋棋⼿马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放⼋个皇后,使其不能互相攻击,即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上,问有多少种摆法。
⾸先来看看这张模拟⼋皇后的图。
这张图说明皇后具有横轴、竖轴以及两个斜轴⽅向的杀伤⼒,也就是像⽶字形⼀样;为了减少判断,我们按照⼀个⽅向往另⼀个⽅向排列,中间不能跳⾏,这样我们就可以只判断已经有皇后的位置,还没有皇后的就可以偷懒不⽤判断了。
我的⽅案是:1.从最下⾯开始排列,然后往上添加,从左往右排列,这样就只需要判断⽐⾃⼰Y坐标低的具有杀伤能⼒的位置有没有皇后就OK ⽅法是把⾃⼰假定要放置皇后的位置的X和Y轴都依据判断特性进⾏处理;例如,左斜线X和Y轴都减1;中间的只需要把Y 轴减1;右边的和左边的相反,X轴加1,Y轴减1;注意处理边界问题。
2.为了找到合适的位置我们需要在查找失败的时候具备回溯的能⼒,就需要退回到前⼀⾏(Y=Y-1,注意XY是否到边界),直⾄能回溯或者全部判断完毕,每次回溯的时候记得X轴要从头开始 3.通过⼀个数据结构记录正在查找的⽅案,通过另⼀个数据结构记录已经找到的⽅案,当然也可以⽤⼀个变量记录⽅案个数下⾯这张⿊⾊背景是其中⼀个⽅案的截图,第⼀⾏代表皇后的坐标xy;后⾯的是棋盘,这⾥输出竖轴是x,横轴是y,从上到下,从左到右,其中*是边界,空格是空区,#是皇后。
#include <iostream>#include <cstring>#include "DTString.h"#include "LinkList.h" // 这⾥使⽤链表存储皇后的位置using namespace std;using namespace DTLib;template <int SIZE> // N皇后问题,SIZE表⽰皇后个数或者棋盘⼤⼩class QueenSolution : public Object{protected:enum { N = SIZE + 2 }; // N表⽰棋盘⼤⼩,为了边界识别,棋盘四周都要加⼀格struct Pos : public Object // ⽅位结构体{Pos(int px = 0, int py = 0) : x(px), y(py) { }int x;int y;};int m_chessboard[N][N]; // 棋盘,0表⽰空位,1表⽰皇后,2表⽰边界Pos m_direction[3]; // 共3个⽅向;⽅向-1、-1表⽰左斜线;0、-1表⽰下⽅;1、-1表⽰右斜线;⾸先从最下⽅开始,所以只需考虑下⾯的⾏。
N皇后问题
1
x1=1 2
x2= 2 3 kill
1
1 2
N皇后问题
回溯到结点2生成结点8, 路径变为(1, 3), 则结点8成为E-结点, 它生成结点9和结点11都会被杀死(即它的儿子表示不可能导 x1=1 致答案的棋盘格局), 所以结点8也被杀死, 应回溯.
1
1
1
2
2
3
x2= 2 x2= 3 3 kill 8 x3=2 9 kill x3=4 11 kill
N皇后问题
例:n=4的n皇后问题的搜索空间
1 2 2 2 3 3 3 4 4 2 6 3 7 8 4 2
14
1 3 34 4 29 4 1 35 1 2 4
4
18
50 1 45 51 2 56 2 1 3 3 61
4
13 3
16
19
1
பைடு நூலகம்
3 24
40 4 1
38 41
3
20
4
22
1
25
3 2
32 36
18 x2= 4
1 1
2
x2= 1 x2 = 3 24 13 19 8 3 x3=2 kill kill kill x3=4 x3=2 x3=3 x2= 2 x2= 3 9 kill 11 14 kill x4=3 15 kill 16 kill
1 2
结点18生成结点29, 结点29成为E结点, 路径变为(2,4); 结点29生成结点30, 路径变为(2,4,1) 结点30生成结点31, 路 径变为(2,4,1,3), 找到一 个4-王后问题的可行解
16 kill
30 x4=3 31
可 行 解
N皇后问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
n后问题问题描述在n×n格的棋盘上放置彼此不受攻击的n个皇后。
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n后问题等价于在n×n 格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
算法分析•解向量:(x1, x2, … , xn)•显约束:xi=1,2, … ,n•隐约束:1)不同列:xi≠xj2)不处于同一正、反对角线:|i-j|≠|xi-xj|算法class Queenfriend int nQueen(int)private:bool Place(int k);void Backtrack(int t);int n, //皇后个数*n; //当前解long sum; //当前已找到的可行方案数bool Queen::Place(int k){for (int j=1;j<k;j++)if ((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k])) return false; return true;}void Queen::Backtrack(int t){if (t>n) sum++; //达到叶结点elsefor (int i=1;i<=n;i++) { //搜索子结点x[t]=i; //进入第i个子结点if (Place(t)) Backtrack(t+1);}}int nQueen(int n){Queen X;//初始化XX.n=n;X.sum=0;int *p=new int [n+1];for(int i=0;i<=n;i++)p[i]=0;X.x=p;X.Backtrack(1); //对整个解空间回溯搜索delete []p;return X.sum;}private://当前种子unsigned long randSeed;public://构造函数,默认值0表示由系统自动产生种子RandomNumber(unsigned long s=0);//产生0:n-1之间的随机整数unsigned short Random(unsigned long n);//产生[0,1)之间的随机实数double fRandom(void);};//产生种子RandomNumber::RandomNumber(unsigned long s){if(s==0) randSeed=time(0); //用系统时间产生种子else randSeed=s; //由用户提供种子}//产生0:n-1之间的随机整数unsigned short RandomNumber::Random(unsigned long n) {randSeed=multiplier*randSeed+adder;return (unsigned short) ((randSeed>>16)%n);}//产生[0,1)之间的随机实数double RandomNumber::fRandom(void){return Random(maxshort)/double(maxshort);}Nqueen LasVegas.cpp#include<iostream>#include "math.h"#include "randomnumber.h"using namespace std;class Queenfriend void nQueen(int);private:bool Place(int k); //测试皇后k置于第x[k]列的合法性bool QueensLV(void); //随机放置n个皇后拉斯维加斯算法int n, //皇后个数*x,y[1000]; //解向量};bool Queen::Place(int k) //Place(k)用于测试将皇后k置于第x[k]列的合法性{for(int j=1;j<k;j++)if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))return false;return true;}bool Queen::QueensLV(void) //QueensLV(void)实现在棋盘上随机放置n个皇后拉斯维加斯算法{RandomNumber rnd; //随机数产生器int k=1; //下一个放置的皇后编号int count=1;while((k<=n)&&(count>0)){count=0;for(int i=1;i<=n;i++){x[k]=i;if(Place(k))y[count++]=i;}if(count>0) x[k++]=y[rnd.Random(count)];//随机位置}return (count>0); //count>0表示放置成功}void nQueen(int n) //解n后问题的拉斯维加斯算法{Queen X; //初始化X.n=n;int * p=new int[n+1];for(int i=0;i<=n;i++)p[i]=0;X.x=p;//反复调用随机放置n个皇后拉斯维加斯算法,直至放置成功while(X.QueensLV()){cout<<"结果是:"<<endl;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(j==p[i])cout<<"Q"<<" ";if(j!=p[i])cout<<"*"<<" ";}cout<<endl;}break;}delete []p;}void main(){int n;cout<<"输入皇后个数:"<<endl;cin>>n;nQueen(n);system("pause");}#include<iostream.h>#include<stdlib.h>void Queen(int i,int n,int *col,int *md,int *sd,int *q) {for(int j=0;j<n;j++){if(!col[j]&&!md[n+i-j-1]&&!sd[i+j]){col[j]=md[n+i-j-1]=sd[i+j]=1;q[i]=j;int time=0;if(i==n-1){for(int k=0;k<n;k++){cout<<k<<", "<<q[k]<<" ";}cout<<endl;}else Queen(i+1,n,col,md,sd,q);col[j]=md[n+i-j-1]=sd[i+j]=0;q[i]=0;}}}void main(){int n;cout<<"Enter n please"<<endl;cin>>n;int *col=new int[n];int *md=new int[2*n-1];int *sd=new int[2*n-1];int *q=new int[n];for(int t=0;t<n;t++){col[t]=0;q[t]=0;}for(int s=0;s<2*n-1;s++) {md[s]=0;sd[s]=0;}Queen(0,n,col,md,sd,q);}#include<stdio.h>#define NUM 8 /*定义数组的大小*/int a[NUM+1];int main(){int i,k,flag,not_finish=1,count=0;i=1; /*正在处理的元素下标,表示前i-1个元素已符合要求,正在处理第i个元素*/ a[1]=1; /*为数组的第一个元素赋初值*/printf("The possible configuration of 8 queens are:\n");while(not_finish) /*not_finish=1:处理尚未结束*/{while(not_finish&&i<=NUM) /*处理尚未结束且还没处理到第NUM个元素*/{for(flag=1,k=1;flag&&k<i;k++) /*判断是否有多个皇后在同一行*/if(a[k]==a[i])flag=0;for(k=1;flag&&k<i;k++) /*判断是否有多个皇后在同一对角线*/if((a[i]==a[k]-(k-i))||(a[i]==a[k]+(k-i))) flag=0;if(!flag) /*若存在矛盾不满足要求,需要重新设置第i个元素*/{if(a[i]==a[i-1]) /*若a[i]的值已经经过一圈追上a[i-1]的值*/{i--; /*退回一步,重新试探处理前一个元素*/if(i>1&&a[i]==NUM)a[i]=1; /*当a[i]为NUM时将a[i]的值置1*/else if(i==1&&a[i]==NUM)not_finish=0; /*当第一位的值达到NUM时结束*/else a[i]++; /*将a[i]的值取下一个值*/}else if(a[i]==NUM) a[i]=1;else a[i]++; /*将a[i]的值取下一个值*/}else if(++i<=NUM)if(a[i-1]==NUM) a[i]=1; /*若前一个元素的值为NUM则a[i]=1*/else a[i]=a[i-1]+1; /*否则元素的值为前一个元素的下一个值*/}if(not_finish){++count;printf((count-1)%3?" [%2d]: ":" \n[%2d]: ",count);for(k=1;k<=NUM;k++) /*输出结果*/printf(" %d",a[k]);if(a[NUM-1]<NUM) a[NUM-1]++; /*修改倒数第二位的值*/else a[NUM-1]=1;i=NUM-1; /*开始寻找下一个足条件的解*/}}}#includeusing namespace std;int width=8,lim=(1< void queen(int col,int ld,int rd) //分别是列,正斜线,反斜线,{//col的二进制位中的1代表该行不能放的地方,ld,rd同理if(col==lim){ans++;return;} //递归终止条件:col的二进制位在width(棋盘宽度)内都是1(放满了)int pos=lim&~(col|ld|rd); //col,ld,rd都是0的位可以放皇后,pos 该位置1while(pos){int t=pos&-pos; //取pos最右边的1位放皇后pos-=t;queen(col|t,(ld|t)<<1,(rd|t)>>1); //往棋盘的下一行递归,左斜线的限制往左,右斜线往右,可以画图看看}}int main(){queen(0,0,0); //cout< return 0;}#include "stdio.h"#include "windows.h"#define N 8 /* 定义棋盘大小 */int place(int k); /* 确定某一位置皇后放置与否,放置则返回1,反之返回0 */void backtrack(int i);/* 主递归函数,搜索解空间中第i层子树 */ void chessboard(); /* 每找到一个解,打印当前棋盘状态 */static int sum, /* 当前已找到解的个数 */x[N]; /* 记录皇后的位置,x[i]表示皇后i放在棋盘的第i行的第x[i]列 */int main(void){backtrack(0);system("pause");return 0;}int place(int k){/* 测试皇后k在第k行第x[k]列时是否与前面已放置好的皇后相攻击。