欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

布线问题-分支限界法c++实现

程序员文章站 2022-03-23 19:44:22
布线问题-分支限界法 问题描述 印刷电路板不限区域划分成n*m个方格阵列。如下图所示 分支限界法类似于回溯法,也是在问题的解空间上搜索问题的解的算法。分支限界法是找出满足约束条件的一个解或者满足某种...

布线问题-分支限界法

问题描述
印刷电路板不限区域划分成n*m个方格阵列。如下图所示

分支限界法类似于回溯法,也是在问题的解空间上搜索问题的解的算法。分支限界法是找出满足约束条件的一个解或者满足某种条件的最优解。分支限界法则以广度优先或者最小耗费优先的方式搜索解空间。

其搜索策略是:

1、在扩展结点处,先生成其所有的儿子结点,然后再从当前的活结点表中选择下一个扩展结点。

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 q;
    do
    {
        for(int i=0;i=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;
}

下面结合布线问题来体会分支限界的思想:代码



算法实现

#include
#include
using namespace std;

//表示方格上位置的结构体
struct position
{
    int row;
    int col;
};

//分支限界算法
bool findpath(position start,position finish,int& pathlen,position *&path,int **grid,int m,int n)
{
    //找到最短布线路径,则返回真,否则返回假

    //起点和终点想同,不用布线
    if((start.row==finish.row) && start.col==finish.col)
    {
        pathlen=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;    //上

    //相邻的方格数
    int numneighblo=4;
    position here,nbr;
    //设置当前方格,即搜索单位
    here.row=start.row;
    here.col=start.col;
    //由于0和1用于表示方格的开放和*,故距离:2-0 3-1
    grid[start.row][start.col]=0;

    //队列式搜索,标记可达相邻方格
    queue q_findpath;

    do
    {
        for(int i=0; i=0; j--)
    {
        path[j]=here;
        //找前驱位置
        for (int i = 0; i <=numneighblo; 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;
}

int main()
{
    cout<<"---------分支限界法之布线问题--------"<>m>>n;

    //创建棋盘格
    int **grid = new int*[m+2];
    for(int i=0; i < m+2; i++)
    {
        grid[i] = new int[n+2];
    }
//初始化棋盘格
    for(int i=1; i <= m; i++)
    {
        for(int j=1; j <=n; j++)
        {
            grid[i][j]=-1;
        }
    }
       //设置方格阵列的围墙
    for(int i=0; i<=n+1; i++)
        grid[0][i]=grid[m+1][i]=-2;//上下的围墙

    for(int i=0; i<=m+1; i++)
        grid[i][0]=grid[i][n+1]=-2;//左右的围墙

    cout<<"初始化棋盘格和加围墙"<>ci>>cj;
        if(ci>m||cj>n)
        {
            cout<<"输入非法!!!!!";
            cout<<"行坐标 < "<