八皇后问题

来源:互联网 发布:学钢琴 软件 编辑:程序博客网 时间:2024/06/01 07:20

八皇后问题是十九世纪著名数学家高斯于1850年提出的。问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上。可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上。

若k表示第几个皇后的话,则用x[k]表示该皇后的列数,该皇后的坐标为(k,x[k]).则题中所要求的拜访规则是

任意的两个皇后i,k,在行列上符合 i!=k && x[i]!=x[k],在斜线上 i+x[i]!=k+x[k] && i-x[i]!=k-x[k],即abs(i-x[k])!=abs(k-x[k]).


朴素算法是8个for循环,在最内层依次判断8个皇后的位置是否符合规则,复杂度为8^8,这是个极为可怕的数字,况且我们可能出现10皇后,16皇后等问题。此题的解法是利用回溯法,其实也是暴力穷举,不同是在我们已知此种情况无解时不在继续往下求解,即进行剪枝过程。

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为:

1、定义一个解空间,它包含问题的解。

2、利用适于搜索的方法组织解空间。

3、利用深度优先法搜索解空间。

4、利用限界函数避免移动到不可能产生解的子空间。

问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。


我们将n*n的表格表示成完全n叉树,此n叉树包换了所有的网格,当然也包含了所有的解,我们从最顶层开始深度优先搜索,等在某个节点不符合规则的情况下进行剪枝,并且回溯到上一层。此题可用递归和非递归两种方法,以下贴上代码:

递归:

#include<iostream>#include<cmath>using namespace std;int x[100];//数组内容表示列数,下标表示第几个皇后int count=0;int num=8;//检测是否符合要求bool ischeck(int k){for(int i=1;i<k;i++){if(x[i]==x[k] || abs(i-k)==abs(x[i]-x[k]) )return false; }return true;}void queue(int k){if(k>8){//找到一个解for(int j=1;j<=num;j++){//打印解printf(" %d ",x[j] );}printf("\n");count++;}else{for(int i=1;i<=num;i++){x[k]=i;if( ischeck(k))queue(k+1);//递归,回溯}}return ;}int main(){//初始化for(int i=0;i<=num;i++){x[i]=0;}queue(1);printf("count=%d\n",count);}

非递归:

#include<iostream>#include<cmath>using namespace std;int x[100];//数组内容表示列数,下标表示第几个皇后int count=0;//检测是否符合要求bool ischeck(int k){for(int i=1;i<k;i++){if(x[i]==x[k] || abs(i-k)==abs(x[i]-x[k]) )return false; }return true;}//n表示皇后个数void queue(int n){//初始化for(int i=0;i<=n;i++)x[i]=0;int k=1;//第一个皇后开始while(k>=1){x[k]=x[k]+1;while( x[k]<=n && !ischeck(k))//第k个皇后找到位置x[k]=x[k]+1;if(k==8 && x[k]<=n){//找到一个解for(int j=1;j<=n;j++){printf(" %d ",x[j]);//x[j]=0;}//k=1;printf("\n");count++;}else if(k<n && x[k]<=n){k=k+1;//查找下一个}else{x[k]=0;//回溯k=k-1;}}}int main(){int n=8;queue(n);printf("count=%d\n",count);return 0;}


我觉得问题的思路在于认识到无用功的计算使我们复杂度得以增加,砍掉了无用功才能使问题简单化。

今天总结:

今天的两道题目是分别是 八皇后和逆序数,用到的思想分别是回溯和分治,两题都是在参考他人解法下才做出来的,所以仅达到了理解,还为掌握应用。

不断学习,不断进步,加油。

0 0
原创粉丝点击