算法(6):分支限界法

我也在学习中,会尝试一下解决所有问题,所以不定期会更改文章,如果有好的思路的欢迎讨论


分支限界法的解题思路:

分支限界法类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。

区别:

回溯法求解目标是找出T中满足约束条件的所有解,分支限界法的求解目标是找出满足约束条件的一个解。

回溯法是深度优先的方式搜索解空间树T

而分支限界法师广度优先


搜索策略:

(1)在扩展结点处,先生成其所有的儿子结点(分支)

(2)然后从当前的活节点表中选择下一个拓展结点

(3)为了有效的选择下一扩展结点,以加速搜索的进程,在每一活结点处计算一个函数值,并根据这些函数值选择一个最有利的结点作为拓展节点,从而找出最优解。


6.2单源最短问题



如上图所示(画的难看。。大概知道意思就好)

如果要找1--8的最短路径,那么首先应该知道1--8有哪些情况,然后找到最短的路径就好了

(1)输入v作为起始坐标点,可以创建一个dist数组存储每个结点到v结点的最短长度,可以创建一个prev数组存储这个结点到达v最短的前驱是什么(v的前驱设置成0方便跳出)

(2)创建一个小堆,以路径长短为排序依据,然后找完一个相邻结点后挑出来一个路径最短的开始找相继后继(直到堆为空则跳出)

(3)所有的找完以后那么所有节点的前驱和到达v结点的最短路径就都知道了

(4)要找最短路径,就输出prev直到没有前驱

(5)求最短路径长度,就直接找dist

dist初始化都设置为无穷大,prev初始化都设置为1,确定v以后可以把dist[v]变成0,prev[v]编程0 

判断是否更改这两项值得条件应该是当前结点i与遍历到的的j结点相邻,edges[i][j]!=NoEdge(表示不相邻无穷大),并且当前长度加上i,j长度要小于原本j到达v的长度也就是dist[j],然后创建相应结点压入最小堆




6.7旅行销售员问题

有许多个点,每个点到另外一个点需要消耗固定金钱,如何每个点只过一遍而且找到所花费金钱最少的那条路线就是我们今天要做的事情。

关于此问题的解空间树是一颗排列树,这里采用使用一个优先队列来存储活结点。

(1)二维数组a[i][j]表示从i->j要花费的金钱

(2)记得设置NoEdge表示当a[i][j]==NoEdge的话那么i,j不相通

(3)首先需要按照要求把a[i][j]初始化,a是n+1行n+1列的(矩阵从0开始,我们不需要0)

(4)设置一个队列记录最优路径,设置一个V记录从那个点开始的最优解

(5)Type Tcp(vector<int>& path,int v)为一个成员函数的声明,通过调用void Backtrack(int i)找出最优路径

(6)cc表示当前,bestc表示最优,如果cc加上某个a[i][j]>bestc那么就可以放弃这一条线路,如果在i==n的时候,cc<bestc,那么就可以把路径给path,一般的,在i!==n的时候,为了遍历到所有的可能性,我们可以从传入的i开始,把i以后的每一个可能性用for循环加上递归带入到程序中去,

for(int j = i;j<=n;++j)

{
if(edges[x[i-1]][x[j]] != NoEdge && 
cc+ edges[x[i-1]][x[j]] < bestc)
{
Swap(x[j],x[i]);
cc+=edges[x[i-1]][x[i]];//i和k换过了,所以这里i-1,i就是i-1,j的值
Backtrack(i+1);
cc-=edges[x[i-1]][x[i]];
Swap(x[j],x[i]);
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值