| 首页 >> 网络编程 >> 程序基础 >> 新闻正文 | [字体:大 中 小] [打印文档] [关闭] |
|
|
|
for (i = 0; i < n; i++) v[i+1] = E.x[i]; while (true) {// 释放最小堆中的所有节点 delete [] E.x; try {H.DeleteMin(E);} catch (OutOfBounds) {break;} } return bestc; } while 循环不断地展开E-节点,直到找到一个叶节点。当s = n - 1时即可说明找到了一个叶节点。旅行路径前缀是x [ 0 : n - 1 ],这个前缀中包含了有向图中所有的n个顶点。因此s = n - 1的活节点即为一个叶节点。由于算法本身的性质,在叶节点上lcost 和cc 恰好等于叶节点对应的旅行路径的耗费。由于所有剩余的活节点的lcost 值都大于等于从最小堆中取出的第一个叶节点的lcost 值,所以它们并不能帮助我们找到更好的叶节点,因此,当某个叶节点成为E-节点后,搜索过程即终止。 while 循环体被分别按两种情况处理,一种是处理s = n - 2的E-节点,这时,E-节点是某个单独叶节点的父节点。如果这个叶节点对应的是一个可行的旅行路径,并且此旅行路径的耗费小于当前所能找到的最小耗费,则此叶节点被插入最小堆中,否则叶节点被删除,并开始处理下一个E-节点。 其余的E-节点都放在while 循环的第二种情况中处理。首先,为每个E-节点生成它的两个子节点,由于每个E-节点代表着一条可行的路径x [ 0 : s ],因此当且仅当< x[s],x[i] > 是有向图的边且x [ i ]是路径x [ s + 1 : n - 1 ]上的顶点时,它的子节点可行。对于每个可行的孩子节点,将边<x[s],x[i] > 的耗费加上E.cc 即可得到此孩子节点的路径前缀( x [ 0 : s ],x[i]) 的耗费c c。由于每个包含此前缀的旅行路径都必须包含离开每个剩余顶点的出边,因此任何叶节点对应的耗费都不可能小于cc 加上离开各剩余顶点的出边耗费的最小值之和,因而可以把这个下限值作为E-节点所生成孩子的lcost 值。如果新生成孩子的lcost 值小于目前找到的最优旅行路径的耗费b e s t c,则把新生成的孩子加入活节点队列(即最小堆)中。 如果有向图没有旅行路径,程序1 7 - 9返回N o E d g e;否则,返回最优旅行路径的耗费,而最优旅行路径的顶点序列存储在数组v 中。 5.2.5 电路板排列 电路板排列问题( 1 6 . 2 . 5节)的解空间是一棵排列树,可以在此树中进行最小耗费分枝定界搜索来找到一个最小密度的电路板排列。我们使用一个最小优先队列,其中元素的类型为B o a r d N o d e,代表活节点。B o a r d N o d e类型的对象包含如下域: x(电路板的排列),s(电路板x[1:s]) 依次放置在位置1 到s 上),c d(电路板排列x [ 1 : s ]的密度,其中包括了到达x[s] 右边的连线),n o w(now[j] 是排列x[1:s] 中包含j 的电路板的数目)。当一个BoardNode 类型的对象转换为整型时,其结果即为对象的cd 值。代码见程序1 7 - 1 0。 |
