布線問題-分支限界法


問題描述:

  印刷電路板不限區域划分成n*m個方格陣列。如下圖所示

  精確的電路布線問題要求確定連接方格a的中點,到連接方格b的中點的最短布線方案。

  布線時,電路只能沿直線或直角布線。為了避免線路相交,已布的線的方格做了封鎖標記,其他線路不允許穿過被封鎖的方格。

分支限界法的解決方案:

  首先從起始位置a開始,將它作為第一個擴展結點。與該節點相鄰,並且可達的方格成為可行結點被加入到活節點隊列中,並且將這些方格標記為1.

    即從起始方格a到這些擴展方格距離為1.

  然后從活節點隊列中取出隊首結點作為下一個擴展結點,並將於當前擴展結點相鄰且為未標記過的方格標記為2,並存入或節點隊列。

  最后這個過程一直到算法搜索到目標方格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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM