您的位置:首页 > 其它

队列的应用—电路布线最优解问题

2013-02-05 20:39 267 查看
首先什么是电路布线问题呢?电路布线问题是类似于迷宫的问题,也是一个模拟矩阵,迷宫是每个点有8个方向可以走,但是在电路布线问题中每个点上只有上下左右4个方向可走。因为电路布线不允许对角线上布线,并且电路布线问题要求线路所走过的路程必须是最短的,即从出发点到目的点路径很可能有很多,要找的是经过跳数最少的那个。也就是说不能太多的弯儿,能直走的就直着走。

迷宫问题是只要找到出路,不管路径是如何的。在寻找通路阶段和走迷宫是差不多的,迷宫是将走过的路存储在栈中,通过试探与回溯的方法一步一步的往前行。此问题不能用栈来做了,而是用队列来辅助实现,因为要将所有的可行的点都走一遍,并把所有可行点距离出发点的路径值也要表示出来,根据这个路径值来找出最短的路径来。

使用一个矩阵来表示一个算是迷宫的东西,用0来表示可通过,用1表示不可通过。下面是模拟矩阵:

1 1 1 1 1 1 1 1

1 0 0 1 0 0 0 1

1 1 0 0 0 1 0 1

1 0 1 1 0 0 0 1

1 0 0 0 1 1 0 1

1 0 1 1 1 0 0 1

1 0 0 0 0 0 0 1

1 1 1 1 1 1 1 1

起点是:(1,1),目的点是(6,3)。

使用结构体来表示每一个点周边可行的路线,这是一个包含行和列值的结构体,Position(row,col)。而且每个点都是四个方向,这其中有的可行有的不可行,将其存储在一个数组中Position offset[offset_num];

以下是数组中不同的元素所代表的不同方向:

row col direc

-1 0 0 上

0 1 1 右

1 0 2 下

0 -1 3 左

下面是Position 类的定义:

#pragma once
#include<iostream>
using namespace std;
class Position
{
public:
int row;//矩阵 行
int col;//矩阵 列
public:
Position();
Position(int r,int c);
~Position();
bool operator== (Position &P);
void operator= (Position &P);
friend ostream& operator<< (ostream& output,Position &P);
friend istream& operator>> (istream& input,Position &P);
};


#include"position.h"
#include<iostream>
using namespace std;
Position::Position()
{}
Position::Position(int r,int c)
{
row = r;
col = c;
}
Position::~Position()
{}
bool Position::operator== (Position &P)
{
return ((row == P.row && col == P.col) ? true : false);
}
void Position::operator= (Position &P)
{
row = P.row;
col = P.col;
}
ostream& operator<< (ostream& output,Position &P)
{
output<<"("<<P.row<<","<<P.col<<")" ;
return output;
}
istream& operator>> (istream& input,Position &P)
{
input>>P.row>>P.col ;
return input;
}
下面是带电路布线类:

#pragma once
#include"position.h"
#include"L_Queue.h"
//以下参数配置在头文件中会更好,在这里不做麻烦了。
const int offset_num = 4;
const int total_row = 8;//模拟矩阵的总行数
const int total_col = 8;//列数

const int start_row = 1;//起始行值
const int start_col = 1;//起始列值

const int finish_row = 6;//终止行值 此为数组下标值所以最大为total_row-1
const int finish_col = 3;//终止列值最大为total_col-1

//const Position start(start_row,start_col);//起始位置
//const Position finish(finish_row,finish_col);//终止位置
class DB//电路布线
{
private:
Position offset[offset_num];//四个移动方向
int grid[total_row][total_col];//一个模拟方格的矩阵
Position here;//当前矩阵位置
Position neighbour;//当前矩阵的可能的邻居位置
Position start;//布线开始位置
Position finish;//布线结束位置
Position *path;//存储的最短路径动态数组
int path_length;//最短路径步数
Queue<Position> qu_pos;//装载位置的队列 靠此遍历方格

bool FindPath();//封装 寻求路径算法
public:
DB();
~DB();
void output();//对外 调用接口

};
#include"电路布线.h"
#include<iostream>
#include<fstream>
using namespace std;
//初始化 一些数据
DB::DB()
{
ifstream in_grid("GRID.txt");
for(int r=0;r<total_row;r++)
{
for(int c=0;c<total_col;c++)
in_grid>>grid[r][c];
}
in_grid.close();

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;//上

start.row = start_row;start.col = start_col;//布线开始
finish.row = finish_row;finish.col = finish_col;//结束

}
DB::~DB()
{}
void DB::output()
{
for(int r=0;r<total_row;r++)
{
for(int c=0;c<total_col;c++)
cout<<grid[r][c]<<" ";

cout<<endl;
}
cout<<start.row<<" "
<<start.col<<endl;
cout<<finish.row<<" "<<finish.col<<endl;

cout<<endl<<endl;
if(FindPath())
{
for(int i=0;i<path_length;i++)
//cout<<path[i].row<<" "<<path[i].col<<endl;
cout<<path[i]<<endl;
}
for(int r=0;r<total_row;r++)
{
for(int c=0;c<total_col;c++)
cout<<grid[r][c]<<" ";

cout<<endl;
}
cout<<"路径步数:"<<path_length<<endl;
}
//布线 算法
bool DB::FindPath()
{
if(finish == start)
{
path_length = 0;//路径步数 为0
return true;//返回真
}
here.row = start.row; here.col = start.col;//把开始位置 标记为当前位置
grid[start.row][start.col] = 2;//把开始位置 定为2 因为矩阵中0表示通路1表示堵塞
while(true)//靠此 无限循环把整个矩阵都赋上路径值 如果可以的情况下
{
for(int i=0;i<offset_num;i++)//此循环 为了把当前的四个邻居中的可以的位置都进队列
{
neighbour.row = here.row + offset[i].row;
neighbour.col = here.col + offset[i].col;//试探下一个位置
if(grid[neighbour.row][neighbour.col] == 0)//该试探位置可行
{
grid[neighbour.row][neighbour.col] = grid[here.row][here.col] +1;//路径值 +1
if(neighbour.row == finish.row && neighbour.col == finish.col)//该试探是结束位置
break;
qu_pos.In_Queue(neighbour);//把试探位置进队列
}
}//if条件右括号
//第一个break之后 再次判断是否到达finish
if(neighbour.row == finish.row && neighbour.col == finish.col)
break;
if(qu_pos.isEmpty() == true)
return false;//如果第一次四次循环之后还是队列无元素 则说明无法到达布线终点

here = qu_pos.De_Queue();//把试探成功后进队列的元素取出赋给了当前的here

}//while循环右括号

//跳出大循环之后 构造路径
path_length = grid[neighbour.row][neighbour.col] - 2;//实际的路径长度(因为之前在起始位置 有+2)
path = new Position[path_length];//动态开辟路径长度空间
here = finish;//把终点赋给当前值 开始反向寻找最小路径
for(int j=path_length-1;j>=0;j--)
{
path[j] = here;//记下当前位置
for(int i=0;i<offset_num;i++)
{
neighbour.row =here.row + offset[i].row;
neighbour.col = here.col + offset[i].col;//到达 临近位置

if(grid[neighbour.row][neighbour.col] == j+2)
break;
}//内层for循环右括号

here = neighbour;

}//外层for循环右括号

return true;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: