n皇后 实验报告
n皇后

实验[4][实验题目]:n皇后专业:信息与计算数学学号:姓名:日期:1.实验目的学习递归算法的算法思想,并将其运用在计算机程序中。
2 实验内容首先学习递归算法的思想然后运用递归算法的思想进行程序编译3.算法设计要解决N皇后问题,其实就是要解决好怎么放置这n个皇后,每一个皇后与前面的所有皇后不能在同一行、同一列、同一对角线,在这里我们可以以行优先,就是说皇后的行号按顺序递增,只考虑第i个皇后放置在第i行的哪一列,所以在放置第i个皇后的时候,可以从第1列判断起,如果可以放置在第1个位置,则跳到下一行放置下一个皇后。
如果不能,则跳到下一列...直到最后一列,如果最后一列也不能放置,则说明此时放置方法出错,则回到上一个皇后向之前放置的下一列重新放置。
此即是回溯法的精髓所在。
当第n个皇后放置成功后,即得到一个可行解,此时再回到上一个皇后重新放置寻找下一个可行解...如此后,即可找出一个n皇后问题的所有可行解。
4.程序代码#include <iostream>using namespace std;int p[12][12];//初始化矩阵(矩阵太大回溯法的效率很低,所以该题的数据很小)int result;int n;//矩阵大小void init(int n)//初始化矩阵{for(int i=0;i<n;i++){for(int j=0;j<n;j++)p[i][j]=0;}result=0;}bool issafe(int row,int col)//判断该位置能否放皇后{for(int i=0;i<row;i++){for(int j=0;j<n;j++){if(p[i][j]==1){//判断同行,同列,对角线上是否有皇后if(i==row||j==col||(j-i)==(col-row)||(j+i)==(col+row))return false;}}}return true;}void putqueen(int x)//入皇后{for(int y=0;y<n;y++)//遍历该行每个位置{if(issafe(x,y))//如果可以{p[x][y]=1;//则放皇后if(x<n-1)putqueen(x+1);//如果未到最后一行,在下一行放皇后elseresult++;//否则返回,结果加1}{for(int k=0;k<n;k++)//该步骤很重要,拿走该行上的皇后p[x][k]=0;}}}int main(){cout<<"请输入皇后数:"<<endl;while(cin>>n){init(n);putqueen(0);cout<<n<<"皇后有"<<result<<"解"<<endl;}return 0;}5 运行结果6 结果分析由于100皇后的解太庞大计算机无法快速的计算出答案,故选择了8皇后进行计算,其结果与其他同学程序的结果进行对后数值大小上一致。
c++n皇后问题(含源码)

一、实验设计方案1、实验内容与目的(简单介绍实验内容,说明实验目的)实验目的:要求在一个n*n的棋盘上放置n个皇后,要求放置的n个皇后不会互相吃掉;皇后棋子可以吃掉它所在的那一行、那一列,以及那两条对角线上的任何棋子。
实验内容:你的具体选择(要详细)通过input.txt文件输入一个数字n,求出n皇后问题,并将结果输出到output.txt文件——————————————————————————————————————2、实验准备工作(阐述解决问题所涉及的算法思想,至少要画一个算法流程图来说明)本实验采用递归算法:递归算法中,首先定义三个bool型变量,分别表示行,对角线,反对角线是否有皇后,若有,则用true表示出来。
用循环,依次求出满足要求的点,如果满足,则放置皇后,然后循环查找能放置下一个皇后的点。
当放置的皇后数目等于行列数时,就调用函数将结果输出。
——————————————————————————————————————二、实验步骤、测试与结果分析1、源程序的设计(在此附上源程序(cpp文件)清单)queen.h 文件:#ifndef __QUEEN_H__#define __QUEEN_H__#include<iostream>#include<fstream>//文件流using namespace std;class queen//定义一个queen类{private:int n;//需要解决的n皇后问题bool *row;//行是否有皇后bool *diag;//对角线是否有皇后bool *backdiag;//反对角线是否有皇后int *x;//皇后问题的解void backtracking(int c);//用于递归求解的函数void output();//文件输出函数public:queen();//构造函数virtual~queen();//析构函数void run()//用于执行递归求解,并计算出所有皇后问题的解{backtracking(1);}};queen::queen(){ifstream in("input.txt",ios::in);if(!in)//当打开失败时{cout<<"打开文件input.txt失败!"<<endl;exit(1);}int num;in>>num;//再文本文件中读取一个数字numn=num;//令n=numrow=new bool[n+1];//分配行所占空间diag=new bool[2*n];//分配对角线所占空间backdiag=new bool[2*n];//分配反对角线所占空间x=new int[n+1];//解所占空间int i;for(i=1;i<=n;i++) row[i]=false;//表示所有行都没有放皇后for(i=1;i<2*n;i++) diag[i]=false;//所有对角线没有放皇后for(i=1;i<2*n;i++) backdiag[i]=false;//所有反对角线没有放皇后in.close();//关闭文件}void queen::backtracking(int c){if(c>n) output();//当放置的皇后数等于行数时,输出结果else{for(int r=1;r<=n;r++)//行循环{if(!row[r] && !diag[n-c+r] && !backdiag[r+c-1])//当(r,c)所在行,对角线,反对角线都没有放置皇后时{row[r]=diag[n-c+r]=backdiag[r+c-1]=true;//这点合符要求,在此处放置皇后x[c]=r;//解为(r,c)backtracking(c+1);//c加一,继续放置下一个皇后row[r]=diag[n-c+r]=backdiag[r+c-1]=false;//清空操作}}}}void queen::output(){static int num=0;//表示当前已经求得的解个数ofstream outfile("output.txt",ios::app);//不写ios::app默认是以ios::out打开,只能得到最后一个解。
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的小方块,咱们的目标就是在这个方块上放四个皇后。
听起来简单吧?但试想一下,放下第一个皇后没问题,她随便摆哪儿都行,棋盘上空荡荡的。
但是当你放下第二个皇后时,哎哟,她可就要考虑第一位皇后的地盘了,不能让她们互相看对方的脸呀。
接下来再放第三个、第四个,感觉压力山大,像是要参加一场马拉松比赛,刚开始风驰电掣,后来就感觉体力不支,越往后越是踌躇满志又心慌慌。
于是,咱们决定采用递归的方式来解决这个问题。
你说,递归是什么鬼?其实就是一种方法,简单点说就是“自己叫自己”。
我们可以从放第一个皇后开始,然后把剩下的事情交给下一个步骤,就像是把作业一层一层递交给老师,直到所有问题都解决为止。
我们可以把当前棋盘的每一行都视为一个新的阶段,逐行逐列地放置皇后。
如果这一步走不通,那就“咱们重来”。
这就像是人生中的很多事情,不顺利的时候就换个思路,继续前进。
当你把第一行的皇后放好,接下来就要检查第二行的每一个位置,看看哪里可以放。
每检查一个位置,就像是在打探敌情,谨慎又小心。
噢,不行,这个位置被第一行的皇后盯上了,得换个地方。
这样一来,你可能会发现,有的地方放不下,有的地方则一片大好,任你选择。
一直检查到棋盘的最后一行,如果成功放下皇后,哇,心里那种成就感,简直像中了大奖一样!可是如果发现放不下,那就要退回去,换个方案,哪怕是从头再来。
这就是递归的魅力,既简单又复杂,似乎在和我们的人生进行一场心灵的对话。
实验四 皇后问题求解

实验实习名实验二皇后问题求解(以下为参考内容,具体内容要求由课程在实验实习指导书中规定。
)一、实验实习目的及要求实验题目:皇后问题求解实验目的:1)以Q-皇后问题为例,掌握回溯法的基本设计策略。
2)掌握回溯法解决Q-皇后问题的算法并实现;3)分析实验结果。
二、实验实习设备(环境)及要求(软硬件条件)实验环境:计算机、C语言程序设计环境三、实验实习内容与步骤实验内容与步骤1.用回溯法求解N-Queen,参考教材算法思想,并实现你的算法。
要求:用键盘输入N;输出此时解的个数,并统计运算时间。
2.给出N=4,5,6时,N-Queen解的个数。
3.尝试增大N,观察运行情况;并理解该算法的时间复杂度。
四、实验实习过程或算法(源程序、代码)源程序:#include<stdio.h>#include<math.h>#include <time.h>int X[10];bool PLACE (int k){int i=1;while(i<k){if (X[i]==X[k] || abs(X[i]-X[k])==abs(i-k) )return false;i=i+1;}return true;}void main(){int k=1,n;int count=0;printf("请输入一个正整数:\n");scanf("%d",&n);double duration;clock_t finish, start;start = clock();while (k>0) //对所有行执行以下语句{X[k] = X[k]+1; //移到下一列while(X[k]<=n && !PLACE(k) ){X[k] = X[k]+1; //移到下一列,再判断}if (X[k] <= n) //找到一个位置{if (k==n) //一个完整的解{//printprintf("the soution is:");for (int t=1;t<=n;t++)printf("%3d",X[t]);printf("\n");count +=1 ;}else{k=k+1;X[k]=0;} //转向下一行}elsek=k-1; //回溯}finish = clock();duration = (double)(finish - start);printf("\n the number of the solutions is %d \n", count);printf( "The count time is %2.6f seconds.\n", duration);}五、实验实习结果分析和(或)源程序调试过程(一)算法理论分析使用回溯算法求解的问题特征,求解问题要分为若干步,且每一步都有几种可能的选择,而且往往在某个选择不成功时需要回头再试另外一种选择,如果到达求解目标则每一步的选择构成了问题的解,如果回头到第一步且没有新的选择则问题求解失败。
实验四N皇后问题求解

实验四N 皇后问题求解、题目1) 以Q-皇后问题为例,掌握回溯法的基本设计策略。
2) 掌握回溯法解决Q-皇后问题的算法并实现;二、算法设计思想回溯法是在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。
当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。
(其实回溯法就是对隐式图的深度优先搜索算法)。
若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。
而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。
判断解是否可行的条件:1. 不在同一行或者同一列,x[i]!=x[j],i!=j2•不在一条斜线上,设两个皇后在(i,j)和(k,l)位置,卜k|!=|j-l|三、程序#include<stdio.h>#include<stdlib.h>int n,stack[100]; // 存当前路径int total; // 路径数int att(int,int);void make(int l) //递归搜索以stack[l]为初结点的所有路径{int i,j; //子结点个数if (l==n+1){total=total+1; // 路径数+1 for(i=1;i<=n;i++)printf(" 输出皇后的列位置%-3d",stack[i]);// 输出第i 行皇后的列位置stack[i]}int att(int l,int i){}for (i=1;i<=n;i++){stack[l]=i; II算符i 作用于生成stack[l-1]产生子状态stack[l];if (!att(l,i))make(l+1);printf("\n");exit; II 回溯} II 再无算符可用,回溯int k;for (k=1;k<l;k++)if (abs(l-k)==abs(stack[k]-i)||i==stack[k])return 1;return 0;}int main(){}四、运行结果printf("N=");scanf("%d",&n);total=0; II 路径数初始化为0make(1); II从结点1出发,递归搜索所有的路径printf("%d\n",total);system("pause");return 0;六、心得体会在解决N皇后的时候一开始有点不止如何着手,因为这里有个N的不确定性,所以选择简单少量的情况进行具体考虑显得相对容易了许多,还有一个值得注意的问题就是如何判断要不要重新开始搜索,并且在已经形成的简单模型基础上进行改进,使之也能满足后面较复杂情况。
八皇后以及N皇后问题分析

⼋皇后以及N皇后问题分析⼋皇后是⼀个经典问题,在8*8的棋盘上放置8个皇后,每⼀⾏不能互相攻击。
因此拓展出 N皇后问题。
下⾯慢慢了解解决这些问题的⽅法:回溯法:回溯算法也叫试探法,它是⼀种系统地搜索问题的解的⽅法。
回溯算法的基本思想是:从⼀条路往前⾛,能进则进,不能进则退回来,换⼀条路再试。
在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满⾜某种要求的可能或最优的情况,从⽽得到整个问题的解。
回溯算法就是解决这种问题的“通⽤算法”,有“万能算法”之称。
N皇后问题在N增⼤时就是这样⼀个解空间很⼤的问题,所以⽐较适合⽤这种⽅法求解。
这也是N皇后问题的传统解法,很经典。
算法描述:1. 算法开始,清空棋盘。
当前⾏设为第⼀⾏,当前列设为第⼀列。
2. 在当前⾏,当前列的判断放置皇后是否安全,若不安全,则跳到第四步。
3. 在当前位置上满⾜条件的情况: 在当前位置放⼀个皇后,若当前⾏是最后⼀⾏,记录⼀个解; 若当前⾏不是最后⼀⾏,当前⾏设为下⼀⾏,当前列设为当前⾏的第⼀个待测位置; 若当前⾏是最后⼀⾏,当前列不是最后⼀列,当前列设为下⼀列; 若当前⾏是最后⼀⾏,当前列是最后⼀列,回溯,即清空当前⾏以及以下各⾏的棋盘,然后当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置; 以上返回第⼆步。
4.在当前位置上不满⾜条件: 若当前列不是最后⼀列,当前列设为下⼀列,返回到第⼆步; 若当前列是最后⼀列,回溯,即,若当前⾏已经是第⼀⾏了,算法退出,否则,清空当前⾏以及以下各⾏的棋盘,然后,当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置,返回第⼆步。
如何判断是否安全:把棋盘存储为⼀个N维数组a[N],数组中第i个元素的值代表第i⾏的皇后位置,这样便可以把问题的空间规模压缩为⼀维O(N),在判断是否冲突时也很简单, ⾸先每⾏只有⼀个皇后,且在数组中只占据⼀个元素的位置,⾏冲突就不存在了, 其次是列冲突,判断⼀下是否有a[i]与当前要放置皇后的列j相等即可。
用回溯算法解n皇后问题实验步骤

湖州师范学院实验报告课程名称:算法实验四:回溯算法一、实验目的1、理解回溯算法的概念,掌握回溯算法的基本要素。
2、掌握设计回溯算法的一般步骤,针对具体问题,能应用回溯算法求解。
二、实验内容1、问题描述1 )n后问题在n×n格的棋盘上放置彼此不受攻击的n个皇后。
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
2)0-1 背包问题需对容量为 c 的背包进行装载。
从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。
对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
每种物品要么放进背包,要么丢弃。
2、数据输入:文件输入或键盘输入。
3、要求:1)完成上述两个问题,时间为2 次课。
2)独立完成实验及实验报告。
三、实验步骤1、理解方法思想和问题要求。
2、采用编程语言实现题目要求。
3、上机输入和调试自己所写的程序。
4、附程序主要代码:1.n后问题:#include<iostream>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) {for (int i = 1; i <= n; i++)cout << x[i] << " ";cout << endl;sum++;}else {for (int i = 1; i <= n; i++) {x[t] = 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;}void main() {int n, set;cout << "请输入皇后个数:"; cin >> n;cout << "可行方案所有解:" << endl;set = nQueen(n);cout << "可行方案数:" << set << endl;}2.0-1背包:#include <stdio.h>#include <conio.h>int n;//物品数量double c;//背包容量double v[100];//各个物品的价值double w[100];//各个物品的重量double cw = 0.0;//当前背包重量double cp = 0.0;//当前背包中物品价值double bestp = 0.0;//当前最优价值double perp[100];//单位物品价值排序后int order[100];//物品编号int put[100];//设置是否装入//按单位价值排序void knapsack(){int i,j;int temporder = 0;double temp = 0.0;for(i=1;i<=n;i++)perp[i]=v[i]/w[i];for(i=1;i<=n-1;i++){for(j=i+1;j<=n;j++)if(perp[i]<perp[j]) perp[],order[],sortv[],sortw[] {temp = perp[i];perp[i]=perp[i];perp[j]=temp;temporder=order[i]; order[i]=order[j]; order[j]=temporder; temp = v[i];v[i]=v[j];v[j]=temp;temp=w[i];w[i]=w[j];w[j]=temp;}}}//回溯函数void backtrack(int i){double bound(int i);if(i>n){bestp = cp;return;}if(cw+w[i]<=c){cw+=w[i];cp+=v[i];put[i]=1;backtrack(i+1);cw-=w[i];cp-=v[i];}if(bound(i+1)>bestp)//符合条件搜索右子数 backtrack(i+1);}//计算上界函数double bound(int i){double leftw= c-cw;double b = cp;while(i<=n&&w[i]<=leftw){leftw-=w[i];b+=v[i];i++;}if(i<=n)b+=v[i]/w[i]*leftw;return b;}int main(){int i;printf("请输入物品的数量和容量:");scanf("%d %lf",&n,&c);printf("请输入物品的重量和价值:");for(i=1;i<=n;i++){printf("第%d个物品的重量:",i);scanf("%lf",&w[i]);printf("价值是:");scanf("%lf",&v[i]);order[i]=i;}knapsack();backtrack(1);printf("最有价值为:%lf\n",bestp);printf("需要装入的物品编号是:");for(i=1;i<=n;i++){if(put[i]==1)printf("%d ",order[i]);}return 0;}5、实验结果:四、实验分析1、:n后问题分析只要不要在同一直线和斜线上就行。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
n皇后实验报告
《n皇后实验报告》
引言
n皇后问题是一个经典的计算机科学问题,旨在找到一种方法,在n×n的棋盘
上放置n个皇后,使得它们互相之间不能攻击到对方。
这个问题不仅在计算机
科学领域有着重要的意义,也在数学和逻辑学中有着深远的影响。
在本实验中,我们将探讨不同解决n皇后问题的方法,并对它们进行实验和比较。
实验方法
我们选择了几种常见的解决n皇后问题的算法,包括暴力搜索、回溯法、遗传
算法和模拟退火算法。
我们使用Python编程语言实现了这些算法,并在不同规模的n值下进行了实验。
我们记录了每种算法的运行时间、内存占用和解的质量,并进行了对比分析。
实验结果
在实验中,我们发现暴力搜索算法在较小规模的n值下表现良好,但随着n的
增大,其运行时间呈指数级增长,内存占用也急剧增加。
回溯法在中等规模的
n值下表现较好,但在大规模n值下也存在性能问题。
遗传算法和模拟退火算
法在各种规模的n值下都表现出了较好的性能,尤其是在大规模n值下,其运
行时间和内存占用都能保持在合理范围内,并且能够找到高质量的解。
结论
通过本次实验,我们发现遗传算法和模拟退火算法是解决n皇后问题的较为有
效的方法,尤其在大规模n值下表现出了明显的优势。
这些算法能够在合理的
时间内找到高质量的解,对于解决实际问题具有一定的实用性。
同时,我们也
意识到在选择解决n皇后问题的算法时,需要根据具体情况来进行选择,不能
一概而论。
希望本实验能够为解决n皇后问题提供一些参考和启发。
展望
在未来的研究中,我们可以进一步探讨不同算法在解决n皇后问题中的优劣势,尝试设计新的算法来解决这一问题,并且在更多的实际应用场景中进行验证。
同时,我们也可以将这些算法应用到其他类似的组合优化问题中,以期能够找
到更加通用和高效的解决方法。
希望通过这些努力,能够为计算机科学和数学
领域的发展做出一些贡献。