n皇后(这里主要介绍8皇后)

初学递归,献丑写个N皇后的递归问题,说起N 皇后的递归问题的,我想大家应该是了解的,不过为了防止有些朋友不知道,我还是在google上把提议给大家复制黏贴一下,这是维基百科上的大家随便看看

八皇后问题最早是由国际国际象棋棋手马克斯·贝瑟尔于1848年提出。之后陆续有数学家对其进行研究,其中包括高斯康托,并且将其推广为更一般的n皇后摆放问题。八皇后问题的第一个解是在1850年由弗朗兹·诺克给出的。诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。

艾兹格·迪杰斯特拉在1972年用这个问题为例来说明他所谓结构性编程的能力[2]

八皇后问题在1990年代初期的著名电子游戏第七访客NDS平台的著名电子游戏雷顿教授与不可思议的小镇中都有出现。

   说了这么多,我还是来说一下八皇后问题,其实说起来八皇后问题一点都不复杂,关键的话  用我自己的话来说的 就是在正确的地方判断,在正确的地方向下递归,在正确的地方回调,在正确的地方结束。。。其实感觉就是在说废话,算法就是用代码来表述出你想的东西,你怎么想的就怎么去做,八皇后应该怎么去想呢,八个皇后放在8*8的格子,每行显然有且只能放一个啰,这就是判断的条件之一啰,既然都说道这了,那么我们很显然的看见每列也只能填一个啰,判断条件之二,判断条件之三不能在斜对角线,这怎么搞呢。。。显然是不能成为等腰直角三角形咯,(能想象的出来吗?),dx!=dy;

好了,我们递归的时候先从第一列开始递归,第一列上可以放在哪呢?第一行,第二行,第三行,第四行,反正一个一个去试,填完第一列,我们接下去要填第二列,填第二例怎么考虑呢,和前面当然一样 分别考虑第一二三四行,如果都不行怎么办,回去,回到第一行,让第一列改变,接下去的每一步都是这样,其实很简单,想清楚就好,下面贴上我的参考代码,(说一下八皇后一共有92种),自己先按照上面的思路写写看,实在不行请参考下面的代码。(有错请指正,大神勿喷);

//八皇后问题
#   include <iostream>
#   include <cstring>
#   include <cmath>
using namespace std;
int a[8]={-1,-1,-1,-1,-1,-1,-1,-1};   //初始化条件表示在没有放置任何一个皇后时候的情况;
int vis[8]; 
int count=0;
bool check(int m){
	memset(vis,0,sizeof(vis));
	int i,j,dx,dy;
	for(i=0;i<m;i++){
		vis[a[i]]++;
	}
	for(j=0;j<8;j++){
		if(vis[j]>1)return false;
	}
	for(i=0;i<m;i++){
		for(j=0;j<m;j++){
			if(i==j)continue;
			dx=abs(i-j);
			dy=abs(a[i]-a[j]);
			if(dx==dy)return false;
		}
	}
	return true;
}
void backtrack(int i){
	if(i==8){
		if(check(i)){
		for(int j=0;j<8;j++){
			cout<<a[j]<<" ";
		}
		count++;
		cout<<endl;
		}
		return ;
	}
	for(int k=0;k<8;k++){
		a[i]=k;                          //试棋子 
		if(check(i)){
			backtrack(i+1);              //如果当前的棋子符合条件 试下一个棋子 
		}
		else{
			a[i]=-1;                     //不符合要求就还原当前的棋子,交给上一个调用它的函数; 
			return ;            
		}
	}
}
int main(){
	backtrack(0);                       //从第0个棋子开始试起; 
	cout<<count;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/haoge9551/article/details/44466593