問題描述:算法
印刷電路板不限區域劃分紅n*m個方格陣列。以下圖所示spa
精確的電路佈線問題要求肯定鏈接方格a的中點,到鏈接方格b的中點的最短佈線方案。code
佈線時,電路只能沿直線或直角佈線。爲了不線路相交,已布的線的方格作了封鎖標記,其餘線路不容許穿過被封鎖的方格。blog
分支限界法的解決方案:隊列
首先,從起始位置a開始,將它做爲第一個擴展結點。與該節點相鄰,而且可達的方格成爲可行結點被加入到活節點隊列中,而且將這些方格標記爲1.it
即從起始方格a到這些擴展方格距離爲1.io
而後,從活節點隊列中取出隊首結點做爲下一個擴展結點,並將於當前擴展結點相鄰且爲未標記過的方格標記爲2,並存入或節點隊列。class
最後,這個過程一直到算法搜索到目標方格b或活結點隊列爲空時截止。變量
實現方案:擴展
初始定義position,私有變量row,col,顯示方格 行 列。
grid[i][j]表示方格陣列的 0 : 開放, 1 :封鎖。
2個方格相同,則沒必要計算,直接返回最小距離。
不然,設置方格圍牆,初始化位移矩陣offset。
表示距離時,0,1已經使用,直接從2開始。所以全部距離最後都要減2.
算法描述
bool FindPath(Position start,Position finish,int& PathLen,Position * &path) { //計算從起始位置start到目標位置finish的最短路線 //找到最短佈線路徑返回true,不然返回false if((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 NumOfNbs = 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<NumOfNbs;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)) breakp;//完成佈線 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 < NumOfNbrs ; 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; }