n皇后问题--回溯算法

一、什么是回溯法

    回溯法是一种选优收索法,按照选优条件深度优先收索。如果发现该结点不是最优结点或死结点,就退回上一步重新选择。能进则进,不进则换,不换则退。

二 、算法要素

(1)首先要确定解的形式==解空间:所有可能解组成的空间

(2)想象解空间的组织结构(可以简单理解为一个树)

(3)探索解空间(其中包含一个重要的概念:隐约束(剪枝函数:约束条件+限界函数))

            剪枝函数:减掉得不到可行解或最优解的分支

                        *扩展结点:一个正在生成孩子得结点

                        *活结点:一个自身已生成,但孩子还没有全部生成的结点

                        *死结点:一个所有孩子都已生成的节点

三、算法设计

(1)定义解空间:n皇后问题就是定义一个n元组:{x1,x2,.........,xn}

(2)解空间的组织结构:可以看成一个n叉树,树的深度为n。

(3)收索解空间:

        *约束条件    if(x[t]==x[j] || t-j==x[t]-x[j]) break;

        *限界条件  不需要

        *收索过程:从根开始,以深度优先遍历的方式进行收索。根结点是活结点,并且是当前的扩展结点。在扩展过程中,当前的扩展结点沿纵深方向移向一个新节点,判断该节点是否满足隐约束。if(0) 则该节点为活结点,并且成为扩展结点,继续深一层的收索;if(1) 则换到该结点的兄弟节点继续收索,如果没有兄弟结点或者都收索完了,则该节点为死结点,收索回溯到父节点----直到根结点变成死结点

四、代码(趣学算法--陈小玉编注内的代码)

#include<iostream>
#include<cmath>
#define M 105
using namespace std;

int n;
int x[M];
int countn;

bool Place(int t){
	bool ok=true;
	for(int j=1;j<t;j++){
		if(x[t]==x[j]||t-j==fabs(x[t]-x[j]))
		{
			ok=false;
			break;
		}
	}
	return ok;
} 


void Backtrack(int t){
	if(t>n){
		countn++;
		for(int i=1;i<=n;i++) cout<<x[i]<<" ";
		cout<<endl;
		cout<<"—————————"<<endl; 
	}
	else
		for(int i=1;i<=n;i++){
			x[t]=i;
			if(Place(t))
				Backtrack(t+1);
		}
}

int main(){
	cout<<"请输入皇后的个数:";
	cin>>n;
	countn=0;
	Backtrack(1);
	cout<<"答案个数:"<<countn<<endl;
	return 0; 
}

五、老子还在懵逼状态。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。


猜你喜欢

转载自blog.csdn.net/qq_40728285/article/details/79995664