布线问题 队列式分支算法

来源:互联网 发布:网页快速抢购js脚本 编辑:程序博客网 时间:2024/06/05 22:36

印刷电路板将布线区域划分成n*m个方格阵列。精确的电路布线问题要求确定链接方格a到方格b的最短布线方案。在布线时,电路只能沿直线或者直角布线。为了避免线路相交,已布了线的方格做了封锁标记(红色方格),其他线路不允许穿过被封锁的方格。





下面讨论用队列式分支界限法来解决布线问题。布线问题的解空间是一个图。解此问题的队列式分支界限法从起始位置a开始将它作为第一个扩展结点。与该结点相邻并且可达的方格成为可行结点被加入到活结点队列中,并且将这些方格标记1,即从起始方格a到这些方格的距离为1.接着从活结点队列中取出首结点作为下一个扩展结点,并将与当前扩展结点相邻且未标记过的方格标记2,并存入活结点队列。这个过程一直持续到算法搜索到目标方格b或者活结点队列为空为止。





在实现上述算法时,首先定义一个表示电路板上方格位置的类Position,它的两个私有成员row和col分别表示方格所在的行和列。在电路板的任何一个方格处,布线可沿右,下,左,上4个方向进行。沿这4个方向的移动分别记为移动0,1,2,3.下表的offset[i].row 和offset[i].col分别给出4个方向的相对位移。


用二维数组grid表示所给方阵。初始时grid[i][j]=0,表示该方格允许布线,而grid[i][j]=1表示该方格被封锁,不允许布线。为了方便处理方格边界的情况,给方阵的四周设置一道围墙,即把周围用附加的已封锁方格(g[i][j]=1)围住。算法一开始先检验起始方格和目的方格是否同位置,如果是,则不必计算,直接返回最短距离0。由于数字0和1用于表示方格的开放/封锁状态,所以表示距离时不用这两个数字,将距离的值都加2。实际距离为标记距离减2。算法具体的描述如下:

bool FindPath(Position start,Position finish,int &PathLen,Position *&Path){//计算从起始位置start到目标位置finish的最短布线路径//找到最短布线路径返回true,否则返回falseif((start.row==finish.row)&&(start.col==finish.col)){ PathLen=0;return true;}//设置围墙for(int i=0;i<=m+1;i++)grid[0][i]=grid[n+1][i]=1; //顶部和底部for(int i=0;i<n+1;i++)grid[i][0]=grid[i][m+1]=1; //左边和右边//初始化相对位移Position offset[4];offset[0].row=0; offset[0].col=1;offset[1].row=1; offset[1].col=0;offset[2].row=0; offset[2].col=-1;offset[3].row=-1; offset[3].col=0;int NumOfNbrs=4;  //相邻方格数Position here,nbr;here.row=start.row;here.col=start.col;grid[start.row][start.col]=2;//标记可达方格位置LinkedQueue<Position>Q;do{//标记可达相邻方格for(int i=0;i<NumOfNbr;i++){nbr.row=here.row+offset[i].row;nbr.col=here.col+offset[i].col;if(grid[nbr.row][nbr.col]==0){//该方格未标记grid[nbr.row][nbr.col]=grid[here.row][here.col]+1;if((nbr.row==finish.row)&&(nbr.col==finish.col)) break; //完成布线Q.Add(nbr);}}//是否达到目标位置finish?if((nbr.row==finish.row)&&(nbr.col==finish.col)) break; //完成布线//活结点队列是否空if(Q.IsEmpty()) return false;  //无解Q.Delete(here);   //取下一个扩展结点}while(true);//构造最短布线路径PathLen=grid[finish.row][finish.col]-2;Path=new Position[PathLen];//从目标位置finish开始向起始位置回溯here=finish;for(int j=PathLen-1;j>=0;j--){path[j]=here;//找前驱位置for(int i=0;i<NumOfNbr;i++){nbr.row=here.row+offset[i].row;nbr.col=here.col+offset[i].col;if(grid[nbr.row][nbr.col]==j+2) break;}here=nbr;   //向前移动}return true;}





原创粉丝点击