- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
9.回溯与分枝限界
回溯法和分枝限界技术;路径搜索算法(回溯和分支限界技术);步骤:
(1)确定问题的可能解空间,即搜索范围
(2)以一种便于搜索的方式组织所有可能的解(一般采用树结构)
(3)以某种方式搜索解空间树,有两种基本方式:
①深度优先搜索(DFS),即回溯技术
②广度优先搜索(BFS),即分支限界技术
(4)在搜索过程中利用判定函数(代价函数或限界函数),通过剪枝来加速搜索过程。还可以通过某种技术(AI),优先搜索最有可能包含最优解的子树,从而提高求解的速度。;深度优先搜索DFS;DFS算法;广度优先搜索BFS;BFS算法:; 广度和深度优先搜索有一个很大的缺陷,就是他们都是在一个给定的状态空间中穷举。这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。他的效率实在太低,甚至不可完成。
所以, 必须进行剪枝!;8皇后问题;上右图是一个可行解。它是怎样得来的呢?它是一个一个试出来的。
由于每行必须恰好有一个皇后,我们依次考虑每一行的每一个皇后。我们把行从上到下编号为0到7,列从左到右编号为0到7,这样,每一个当前摆放皇后的“情况”(不一定是解!)可以表示成一个向量,表示每行的皇后编号(列号)。
下图表示为(0, 4, 7, 5, 2, 6, 1, 3)。如果向量中的元素有不确定的值,可以用?表示。由于这时候我们需要进一步确定这些?的值,称每个带?的向量为“状态”。例如(0, 1, ?, ?, ?, ?, ?, ?)就是一个状态。但这个状态并不包含可行解,因为前两个皇后已经相互攻击了。这样的状态称为非法状态。;为简单起见,考虑4*4棋盘上4皇后的问题。
最开始什么都不知道,状态为(?, ?, ?, ?),称为初始状态(initial state) 。第一个皇后在哪一列呢?不知道,只能一个一个试。于是从初始状态可以扩展(expand) 出4个状态,即(0, ?, ?, ?),(1, ?, ?, ?), (2, ?, ?, ?)和(3, ?, ?, ?)。每个状态又继续扩展,直到求出解或者无法扩展为止。这里把完整的过程画出来,如下图。注意:图上并没有画出(0, 1, ?, ?)这样的非法状态。;上图是一棵树,它标识从初始状态可以直接或间接扩展出的所有状态。它有一个名字叫“解答树”,每个结点的儿子是该结点能扩展出的所有结点。每个状态的深度恰好是它包含的问号个数。
只要某算法能完整的扩展出这棵树,它一定可以找到深度为4的所有结点,即问题的解。这样的算法有很多,回溯法就是其中的一个。;回溯法(backtracking) 回溯法按照深度优先的顺序遍历解答树。换句话说,它遍历图3的顺序是(?,?,?,?) - (0,?,?,?) - (0,2,?,?) - (0,3,?,?) - (0,3,1,?) - (1,?,?,?) - (1,3,?,?) -…
既然是深度优先遍历,回溯法可以很自然的写成递归的形式。
下面给出完整的程序,它将按顺序给出回溯法遍历到的所有状态并给出解的总数。为了方便判断,程序使用数组used[i][0],used[i][1]和used[i][2]分别表示编号为i的列、主对角线和副对角线是否已经被攻击到。放置一个皇后需要把一些值设置为真,取走皇后(即回溯)时把这些值重新设置为假。主副对角线分别用y-x和x+y标识各条对角线(对对角线上的点,其y-x值和x-y值保持不变);# include stdio .h
const int n = 4; int tot = 0;
int path [n]; int used [n *2 -1][3];
void search (int dep ){
int i;
if(dep == n) tot ++; //递归边界,得到了一个结果
else for(i = 0; i n; i ++) //枚举第行皇后的列编号dep
if (!used [i ][0] !used[i-dep+n-1][1]!used [i+dep][2]){//不冲突,继续走
path [dep ] = i;
used [i ][0] = used [i-dep+n -1][1] = used [i+dep ][2] = 1;//放置皇后,记录其行列对角
search (dep + 1); //递归遍历子树
used [i ][0] = used [i-dep+n -1][1] = used [i+dep ][2] = 0;//取走皇后,设置状态
文档评论(0)