电路板排线问题的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
*/