算法与程序设计:分支限界法

Posted Abro.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法与程序设计:分支限界法相关的知识,希望对你有一定的参考价值。

目录

一、概念

1.1 分支限界法的基本思想

1.2 分支限界法与回溯法的不同

1.3 分支限界法的搜索方式

1.4 常见的两种分支限界法

二、举例

2.1 单源最短路径问题

三、代码实现

3.1 源程序

3.2 运行结果


一、概念

1.1 分支限界法的基本思想


1.2 分支限界法与回溯法的不同


1.3 分支限界法的搜索方式


1.4 常见的两种分支限界法


二、举例

2.1 单源最短路径问题

下图是用优先队列式(FIFO)分支限界法解有向图G的单源最短路径问题的解空间树;其中,每一个结点旁边的数字表示该结点所对应的当前路长。

找到一条路径:

目前的最短路径是8,一旦发现某个结点的下界不小于这个最短路径,则剪枝:

同一个结点选择最短的到达路径:

剪枝的策略:

1、在算法扩展结点的过程中,一旦发现一个结点的下界不小于当前找到的最短路长,则算法剪去以该结点为根的子树。

2、在算法中,利用结点间的控制关系进行剪枝。从源顶点s出发,2条不同路径到达图G的同一顶点。由于两条路径的路长不同,因此可以将路长较长的路径所对应的树中的结点为根的子树剪去。

最终结果:

所以从源顶点到终点的最短路径值为8,最短路径为:0 2 6 9 10。


三、代码实现

3.1 源程序

package SufaLjh.Exp1.Homework_8.Day_6_11;


import SufaLjh.Exp1.Homework_8.Day_6_11.tool.Heap;
import SufaLjh.Exp1.Homework_8.Day_6_11.tool.HeapNode;

/**
 * 分支限界法求单源最短路径问题
 */
public class E2 {
    //定义变量
    int heapsize = 0,n=10,inf = 1000;//inf 表示距离为无穷
    int c[][] = new int[11][11],dist[]=new int[11],prev[]=new int[11];

    /**
     * 主方法 程序入口
     * @param args
     */
    public static void main(String[] args) {
        new E2();
    }
    public E2(){
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= n; j++)c[i][j] = inf;
            dist[i]=inf;
        }
        c[0][1]=2;c[0][2]=3;c[0][3]=4;
        c[1][2]=3;c[1][4]=7;c[1][5]=2;
        c[2][5]=9;c[2][6]=2;
        c[3][6]=2;c[4][7]=1;c[4][8]=2;c[5][6]=1;c[5][8]=3;
        c[6][8]=5;c[6][9]=1;c[7][10]=2;c[8][10]=2;
        c[9][8]=2;c[9][10]=2;

        Shostestpaths(0,10);
        System.out.printf("从源点到最后一个点的最短路径的值为:%d\\n",dist[10]);
        print(10);
    }

    /**
     * 分支限界法
     * @param v 源点
     * @param end 终点
     */
    private void Shostestpaths(int v,int end){
        Heap heap = new Heap();
        HeapNode E = new HeapNode(),N = new HeapNode();
        E.i=v;E.d=0;
        dist[v]=0;
        while (true){
            for (int j = 1; j <= n; j++) {//找当前节点(下标为E,i)的所有儿子节点
                 //int d=E.d+c[E.i][j];
                 //if (c[E.i][j]<inf&&d<dist[j]&&d<dist[end])
                if (c[E.i][j]<inf&&E.d+c[E.i][j]<dist[j]&&E.d<dist[end]){
                     dist[j]=E.d+c[E.i][j];//更新到第j个顶点的最短距离
                     prev[j]=E.i;//取到第j个顶点的最短距离时,第j个顶点的前一个顶点为E.i
                     N.i=j;N.d=dist[j];//给堆的新节点赋值
                     N.key=N.d;//用最短距离作为堆中关键值
                     heap.minHeapInsert(N);//将所有节点插入堆中
                 }
            }
            E=heap.minHeapDelete();//取出堆顶元素作为当前节点
            if (E.key==-1)break;//堆为空时退出
        }
    }

    /**
     * 打印输出的方法
     * @param v 源点
     */
    private void print(int v) {
        int t[] = new int[11];
        int i = v,j=0;
        while (i>0){
            t[j++]=i;i=prev[i];
        }
        t[j]=0;
        System.out.printf("最短路径为:");
        for (; j >= 0; j--) {
            System.out.printf("%d ",t[j]);
        }
    }
}


 

定义最大堆和最小堆的类文件Heap.java:
package SufaLjh.Exp1.Homework_8.Day_6_11.tool;


//大顶堆
public class Heap {
    int heapsize=0;//堆的大小
    HeapNode A[]=new HeapNode[1000];//存放堆的数组

    /**
     * 主方法
     * @param args
     */
    public static void main(String[] args) {
        new Heap();
    }
    /*public Heap(){

    }*/

    /**
     * 构造器
     */
    public Heap() {
        for(int i=0;i<1000;i++)A[i]=new HeapNode();
        /*System.out.println("小顶堆:");
        //System.out.println("大顶堆: ");
        for (int i = 0; i < 10; i++) {
            HeapNode heapNode = new HeapNode();
            heapNode.key = i;
            //maxHeapInsert(heapNode);
            minHeapInsert(heapNode);
        }*/
        //HeapNode E = maxHeapDelete();
        HeapNode E = minHeapDelete();
        while (E.key!=-1){
            System.out.println(E.key+"  ");
            //E=maxHeapDelete();
            E=minHeapDelete();
        }
    }

    //大顶堆插入
    public  void maxHeapInsert(HeapNode a) {
            heapsize++;
            int i = heapsize;
            while (i > 1 && A[i / 2].key < a.key) {
                A[i].clone(A[i/2]);
                i=i/2;
            }
            A[i].clone(a);
        }
    //大顶堆返回堆顶元素
    public  HeapNode maxHeapDelete() {
            if (heapsize < 1) {
                A[0].key = -1;
                A[0].i = 0;
                return A[0];
            }
            HeapNode max = new HeapNode();
            max.clone(A[1]);
            A[1].clone(A[heapsize]);
            heapsize--;
            maxHeapify(1);//堆化
            return max;
        }
    //大顶堆堆化
    public  void maxHeapify(int i) {
            int L, R, max;
            L = 2 * i;
            R = 2 * i + 1;
            if (L <= heapsize && A[L].key > A[i].key)
                max = L;
            else
                max = i;
            if (R <= heapsize && A[R].key > A[max].key)
                max = R;
            if (max != i) {
                HeapNode t = new HeapNode();
                t.clone(A[i]);A[i].clone(A[max]);A[max].clone(t);
                maxHeapify(max);
            }
        }
    //小顶堆
    public void minHeapInsert(HeapNode a)
    {
        heapsize++;
        int i=heapsize;
        while(i>1&&A[i/2].key>a.key)
        {
            A[i].clone(A[i/2]);
            i=i/2;
        }
        A[i].clone(a);
    }

    public HeapNode minHeapDelete()
    {
        if(heapsize<1){A[0].key=-1;return A[0];}
        HeapNode min=new HeapNode();
        min.clone(A[1]);
        A[1].clone(A[heapsize]);
        heapsize--;
        minHeapify(1);
        return min;
    }
    //小顶堆堆化
    public void minHeapify(int i)
    {
        int L,R,min;
        L=2*i;
        R=2*i+1;
        if(L<=heapsize&&A[L].key<A[i].key) min=L;
        else min=i;
        if(R<=heapsize&&A[R].key<A[min].key) min=R;
        if(min!=i)
        {
            HeapNode  t=new HeapNode();
            t.clone(A[i]);A[i].clone(A[min]);A[min].clone(t);           
            minHeapify(min);
        }
    }

}

定义堆节点的类文件HeapNode.java:
package SufaLjh.Exp1.Homework_8.Day_6_11.tool;

public class HeapNode {
    public int ew,wt,i,x,key,d;
    public double p, up;
    public void clone(HeapNode t) {
        this.i=t.i;
        this.ew=t.ew;
        this.wt=t.wt;
        this.x=t.x;
        this.p=t.p;
        this.up=t.up;
        this.key=t.key;
        this.d=t.d;
    }
}

3.2 运行结果


算法与程序设计的复习嘻嘻嘻蟹蟹٩('ω')و 

 

以上是关于算法与程序设计:分支限界法的主要内容,如果未能解决你的问题,请参考以下文章

五大常用算法:分支限界法

两道关于回溯法,分支限界法的算法题

六中常用算法设计:穷举法分治法动态规划贪心法回溯法和分支限界法

六中常用算法设计:穷举法分治法动态规划贪心法回溯法和分支限界法

回溯法与分支限界

优先队列式分支限界法-最小重量机器设计问题