算法与程序设计:分支限界法
Posted Abro.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法与程序设计:分支限界法相关的知识,希望对你有一定的参考价值。
目录
一、概念
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 运行结果
算法与程序设计的复习嘻嘻嘻蟹蟹٩('ω')و
以上是关于算法与程序设计:分支限界法的主要内容,如果未能解决你的问题,请参考以下文章
六中常用算法设计:穷举法分治法动态规划贪心法回溯法和分支限界法