当前位置:   article > 正文

分支限界法

分支限界法

 什么是分支限界法

        广度优先搜索是—种依照“由近及远,按层展开”的策略进行的枚举算法,也意味着它需要遍历整个状态空间图,导致算法效率不高。给定一个问题的状态间表示,设计搜索算法时需要考虑以下两个事实
       ◆并不是所有的分支都包含可行解
       ◆并不是所有的分支都包含最优解
      分支限界算法=广度优先搜索+剪枝策略

      分支限界算法需要设计合适的剪枝策略,限制某些分支的扩展,尽量避免不必要的搜索。常用的剪枝策略包括两大类
     1.约束函数剪枝:根据约束条件,状态空间图中的部分状态可能是不合法的。因此,在状态空间图中以不合法状态为根的分支不包含可行解,故其分支可以剪枝。
     2.限界函数剪枝:这种策略一般应用于最优化问题。假设搜索算法当前访问的状态为S,且存在一个判定函数:它能判定以S为根的分支不包含最优解,因此该分支可以剪除而无需搜索


    约束函数剪枝可以剪除状态空间图中的不可行解
    限界函数剪枝用于剪除状态空间图中的可行但是非最优的解

             

经典应用

       装载问题
       0-1背包问题
       旅行商问题
       最短路径问题

 

装载问题:

 

TSP问题:

借鉴:https://blog.csdn.net/qq_35649945/article/details/93056866

问题描述:

       旅行家要旅行n个城市,已知各城市之间的路程。要求选定一条从驻地出发经过每个城市一次,最后回到驻地的路线,使总的路程最小。例如:从如图中的无向带权图G=(V,E)中的1号点出发,经过图中的每个点,并且不能重复,然后回到1号点,要求经过的路径长度是最短的(即求图中 路径 )。

                                          å¨è¿éæå¥å¾çæè¿°

算法思想:

定义解空间树后,对解空间进行搜索,需要先找到限界条件和约束条件
(1)约束条件:如果带权邻接矩阵maps[i][j]不为无穷,即<i,j>能走通,否则继续寻找能走通的路。队列不为空。
(2)限界条件:cl<bestw,cl初始值为0,bestw初始值为无穷。
   cl表示当前已走过的路径长度。
搜索过程:
       将满足条件(即上一层节点的路径长度+上层节点到扩展节点的长度<bestw)的节点加入队列,为了加快搜索速度,使用优先队列,优先队列中的优先级为已走过的路径长度cl,cl值越小,越优先。

                                   

  1. import java.util.Arrays;
  2. import java.util.Comparator;
  3. import java.util.PriorityQueue;
  4. import java.util.Scanner;
  5. class Node1{
  6. int cl; //已经走过的路径长度
  7. int id;//表示所在解空间树的第几层
  8. int x[]=new int[105];//存储路径
  9. public Node1(int cl,int id){
  10. this.cl=cl;
  11. this.id=id;
  12. }
  13. }
  14. public class Main {
  15. static final int MAX=105;
  16. static final int INF=(int)1e9;
  17. //优先队列存储,每次自动排序,cl小的优先处理
  18. static PriorityQueue<Node1> q=new PriorityQueue<Node1>(new Comparator<Node1>() {
  19. public int compare(Node1 o1, Node1 o2) {
  20. if(o1.cl>o2.cl) return 1;
  21. else return -1;
  22. }
  23. });
  24. static int g[][]=new int[MAX][MAX];
  25. static int bestw;//最短路径长度
  26. static int best[]=new int[MAX];//最短路径
  27. static int n,m;//n个点,m条边
  28. static void bfs(){
  29. Node1 node=new Node1(0,2);//初始经过的路径为0,起点1位于第树的第二层
  30. for(int i=1;i<=n;i++)
  31. node.x[i]=i;
  32. q.add(node);
  33. while(!q.isEmpty()){
  34. Node1 newnode=q.poll();
  35. int t=newnode.id;
  36. if(t==n){
  37. if(g[newnode.x[t-1]][newnode.x[n]]!=INF && g[newnode.x[n]][newnode.x[1]]!=INF){
  38. if(newnode.cl+g[newnode.x[t-1]][newnode.x[n]]+g[newnode.x[n]][newnode.x[1]]<bestw){
  39. bestw=newnode.cl+g[newnode.x[t-1]][newnode.x[n]]+g[newnode.x[n]][newnode.x[1]];
  40. for(int i=1;i<=n;i++){
  41. best[i]=newnode.x[i];
  42. }
  43. }
  44. }
  45. }
  46. if(newnode.cl>=bestw) continue;//约束条件 两点不可达
  47. //对当前节点进行扩展子节点
  48. for(int j=t;j<=n;j++){
  49. if(newnode.cl+g[newnode.x[t-1]][newnode.x[j]]<bestw){ //限界条件
  50. int c=newnode.cl+g[newnode.x[t-1]][newnode.x[j]];
  51. node=new Node1(c,t+1);
  52. for(int i=1;i<=n;i++){
  53. node.x[i]=newnode.x[i];
  54. }
  55. //通过交换实现路径节点更新
  56. int tmp=node.x[t];
  57. node.x[t]=node.x[j];
  58. node.x[j]=tmp;
  59. q.add(node);
  60. }
  61. }
  62. }
  63. }
  64. public static void main(String[] args) {
  65. Scanner scan=new Scanner(System.in);
  66. n=scan.nextInt();
  67. m=scan.nextInt();
  68. for(int i=0;i<n;i++){
  69. Arrays.fill(g[i], INF);
  70. }
  71. for(int i=0;i<m;i++){
  72. int a=scan.nextInt();
  73. int b=scan.nextInt();
  74. int c=scan.nextInt();
  75. g[a][b]=g[b][a]=c;
  76. }
  77. bestw=INF;//最短路径初始为0
  78. bfs();
  79. System.out.println("最短路径长度:"+bestw);
  80. for(int i=1;i<=n;i++){
  81. System.out.println(best[i]);
  82. }
  83. System.out.println(best[1]);
  84. }
  85. }
  86. //4 6
  87. //1 2 15
  88. //1 3 30
  89. //1 4 5
  90. //2 3 6
  91. //2 4 12
  92. //3 4 3


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/629986
推荐阅读
相关标签
  

闽ICP备14008679号