求解最短路径之电路布线

a和b之间的最短路径需要在两个过程中确定。一个是距离标记过程,另一个是路径标记过程。在距离标记过程中,先从位置a开始,把从a可到达的相邻方格都标记为1(表示与a相距为1),然后把从编号为1的方格可到达的相邻方格都标记为2(表示也a相邻为2)。这个标记过程继续下去直到到达b或者没有可到达相邻方格为止。
距离标记过程结束之后,路径标记过程开始。从方格b开始首先移动到一个其编号比b的编号小1的相邻位置上。重复这个过程直至到达a为止。
为了实现距离标记过程,我们可以使用另外一个数组存储距离,亦可以重用数组grid。为了节约内存我们一般使用数组重用,但是这样障碍物会和距离为1的方格混合,所以我们选择将所有的距离标志都加2。

bool findpath()
{
    if((start.row==finish.row)&&(start.col==finish.col))
    {
        pathLength=0;
        return true;
    }
    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;//上

    //初始化网络四周的weiqiang
    for(int i=0;i<=size+1;i++)
    {
        grid[0][i]=grid[size+1][i]=1;//底部和顶部
        grid[i][0]=grid[i][size+1]=1;//左边和右边
    }
    position here=start;
    grid[start.row][start.col]=2;
    int numOfNbrs=4;
    //对可达的位置做标记
    arrayQueue<position>q;
    position nbr;
    do{
        //给相邻位置做标记
        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]==0)
            {
                grid[nbr.row][nbr.col]=grid[here.row][here.col]+1;
                if((nbr.col==finish.row)&&(nbr.col==finish.col))
                    break;
                q.push(nbr);
            }

        }
        if((nbr.row==finish.row)&&(nbr.col==finish.col))break;
        if(q.empty())
            return false;
        here=q.front();
        q.pop();        
    }while(true);

    //构造路径
    pathLength=grid[finish.row][finish.col]-2;
    path=new position[pathLength];

    //从终点回溯
    here=finish;
    for(int j=pathLength-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;
}

代码解析:首先将开始点周围的0点(即可标记点)加一,然后将周围已标记点插入到队列,然后每次从队列头提取一个点并删除,然后将其周围的可标记点在其基础上加1。知道队列为空或者到达结束点。
然后在结束点开始回溯,每次寻找标记比前一个位置少一的节点。直到开始点。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值