一、什么是回溯法
回溯法是一种选优收索法,按照选优条件深度优先收索。如果发现该结点不是最优结点或死结点,就退回上一步重新选择。能进则进,不进则换,不换则退。
二 、算法要素
(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; }
五、老子还在懵逼状态。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。