队列的应用—电路布线最优解问题
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 类的定义:
迷宫问题是只要找到出路,不管路径是如何的。在寻找通路阶段和走迷宫是差不多的,迷宫是将走过的路存储在栈中,通过试探与回溯的方法一步一步的往前行。此问题不能用栈来做了,而是用队列来辅助实现,因为要将所有的可行的点都走一遍,并把所有可行点距离出发点的路径值也要表示出来,根据这个路径值来找出最短的路径来。
使用一个矩阵来表示一个算是迷宫的东西,用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; }
相关文章推荐
- c++ 数据结构 队列应用之电路布线
- Uva11997 优先级队列的应用 多路合并问题
- 栈和队列的应用:迷宫问题
- 球钟问题(栈和队列的应用)
- 队列应用之售票窗口问题_legend
- 电路布线问题的几种动态规划算法
- 算法复习-----------利用列队解决电路布线问题
- 电路布线问题
- 队列应用-素数环问题
- 算法设计--电路布线问题(分支限界法求解)
- Matlab电路原理应用——求解原本要求用电源等效变换解决的问题
- 电路布线问题
- 舞伴配对问题---队列的应用
- 循环队列的应用——舞伴配对问题(数据结构 C语言)
- 数据结构算法问题 栈与队列的应用
- DP动态规划-电路布线问题
- 【动态规划】电路布线问题
- 舞伴配对问题---队列的应用
- priority_queue 优先级队列的基本应用和重载问题
- 农夫过河问题-队列的应用