• 布线问题分支限界法


    问题描述:

      印刷电路板不限区域划分成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;
    }
  • 相关阅读:
    React16+Redux 实战企业级大众点评Web App
    一类图上二选一构造问题
    O(1)判断两点之间是否有边
    ARC112F Die Siedler
    【学习笔记】同余最短路
    CF1034D Intervals of Intervals
    CF1034C Region Separation
    CF650E Clockwork Bomb
    莫队题三道(LOJ6273, CF1476G, CF700D)
    CF1290D Coffee Varieties (hard version)
  • 原文地址:https://www.cnblogs.com/xing901022/p/2756523.html
Copyright © 2020-2023  润新知