算法java实现--分支限界法--电路板排线问题

电路板排线问题的java实现(优先队列式分支限界法)

具体问题描述以及C/C++实现参见网址

http://blog.csdn.net/liufeng_king/article/details/8952161



import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * 电路板排线问题
 * @author Administrator
 *
 */



public class Bboard {
	/**
	 * 优先队列式分支限界法解决电路板排线问题
	 * @param board
	 * @param m
	 * @param bestx
	 * @return
	 */
	public static int bbBoards(int[][] board,int m,int[] bestx){
		int n=board.length-1;
		LinkedList<Heapno> heap=new LinkedList<Heapno>();
		//初始化
		Heapno enode=new Heapno(0,new int[m+1],0,new int[n+1]);
		//total[i]=连接块中i中电路板数
		int[] total=new int[m+1];
		for(int i=1;i<=n;i++){
			enode.x[i]=i;//初始排列为1,2,...,n
			for(int j=1;j<=m;j++)
				total[j]+=board[i][j];
		}
		int bestd=m+1;
		int[] x=null;
		do{
			//结点扩展
			if(enode.s==n-1){
				//仅一个儿子结点
				int ld=0;//最后一块电路板的密度
				for(int j=1;j<=m;j++)
					ld+=board[enode.x[n]][j];
				if(ld<bestd){
					//找到密度更小的电路板排列
					x=enode.x;
					bestd=Math.max(ld, enode.cd);
				}
			}else{
				//产生当前扩展结点的所有儿子结点
				for(int i=enode.s+1;i<=n;i++){
					Heapno node=new Heapno(0,new int[m+1],0,new int[n+1]);
					for(int j=1;j<=m;j++)
						//新插入的电路板
						node.now[j]=enode.now[j]+board[enode.x[i]][j];
					int ld=0;//新插入电路板的密度
					for(int j=1;j<=m;j++){
						if(node.now[j]>0&&total[j]!=node.now[j])
							ld++;
					}
					node.cd=Math.max(ld, enode.cd);
					if(node.cd<bestd){
						//可能产生更好的结点
						node.s=enode.s+1;
						for(int j=1;j<=n;j++)
							node.x[j]=enode.x[j];
						node.x[node.s]=enode.x[i];
						node.x[i]=enode.x[node.s];
						heap.add(node);
						Collections.sort(heap);
					}
				}
			}
			//取下一个扩展结点
			enode=(Heapno) heap.poll(); 
		}while(enode!=null&&enode.cd<bestd);
		for(int i=1;i<=n;i++)
			bestx[i]=x[i];
		return bestd;
	}
	
	public static void main(String[] args) {
		int m=5;//连接块数
		int n=8;//电路板数
		int[][] b=new int[n+1][m+1];
		System.out.println("n块电路板为{B={1,2,3,4,5,6,7,8}");
		System.out.println("m个连接为:N1={4,5,6};N2={2,3};N3={1,3};N4={3,6};N5={7,8}");
		System.out.println("请输入二维数组b,其中b[i][j]值为1表示电路板i在连接块Nj中:");
		Scanner sc=new Scanner(System.in);
		for(int i=1;i<=n;i++){
			String str=sc.nextLine();
			String[] s=str.split(" ");
			for(int j=1;j<=m;j++){
				b[i][j]=Integer.parseInt(s[j-1]);
			}
		}
		int[] bestx=new int[n+1];
		int bestd=bbBoards(b,m,bestx);
		System.out.println("最小密度为:"+bestd);
		System.out.print("最优排列为:");
		for(int j=1;j<bestx.length;j++){
			System.out.print(bestx[j]+" ");
		}
	}
	
}

class Heapno implements Comparable{
	int s;//x[1:s]是当前节点所相应的部分排列
	int cd;//x[1:s]的密度
	int[] now;//now[j]是x[1:s]所含连接块j中电路板数
	int[] x;//x[1:n]记录电路板排列
	
	//构造方法
	public Heapno(int cdd,int[] noww,int ss,int[] xx){
		cd=cdd;
		now=noww;
		s=ss;
		x=xx;
	}
	
	public int compareTo(Object x){
		int xcd=((Heapno) x).cd;
		if(cd<xcd) return -1;
		if(cd==xcd) return 0;
		return 1;
	}
}
/*
输入:
0 0 1 0 0
0 1 0 0 0
0 1 1 1 0
1 0 0 0 0
1 0 0 0 0
1 0 0 1 0
0 0 0 0 1
0 0 0 0 1

输出:
最小密度为:2
最优排列为:7 8 4 5 6 3 1 2 


 */
    原文作者:分支限界法
    原文地址: https://blog.csdn.net/lican19911221/article/details/27055249
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞