算法复习-----------利用列队解决电路布线问题

首先什么是电路布线问题呢?电路布线问题是类似于迷宫的问题,也是一个模拟矩阵,迷宫是每个点有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 类的定义:

[cpp]  view plain copy
  1. #pragma once  
  2. #include<iostream>  
  3. using namespace std;  
  4. class Position  
  5. {  
  6. public:  
  7.     int row;//矩阵 行  
  8.     int col;//矩阵 列  
  9. public:  
  10.     Position();  
  11.     Position(int r,int c);  
  12.     ~Position();  
  13.     bool operator== (Position &P);  
  14.     void operator= (Position &P);  
  15.     friend ostream& operator<< (ostream& output,Position &P);  
  16.     friend istream& operator>> (istream& input,Position &P);  
  17. };  

[cpp]  view plain copy
  1. #include"position.h"  
  2. #include<iostream>  
  3. using namespace std;  
  4. Position::Position()  
  5. {}  
  6. Position::Position(int r,int c)  
  7. {  
  8.     row = r;  
  9.     col = c;  
  10. }  
  11. Position::~Position()  
  12. {}  
  13. bool Position::operator== (Position &P)  
  14. {  
  15.     return ((row == P.row && col == P.col) ? true : false);  
  16. }  
  17. void Position::operator= (Position &P)  
  18. {  
  19.     row = P.row;  
  20.     col = P.col;  
  21. }  
  22. ostream& operator<< (ostream& output,Position &P)  
  23. {  
  24.     output<<"("<<P.row<<","<<P.col<<")" ;  
  25.     return output;  
  26. }  
  27. istream& operator>> (istream& input,Position &P)  
  28. {  
  29.     input>>P.row>>P.col ;  
  30.     return input;  
  31. }  
下面是带电路布线类:

[cpp]  view plain copy
  1. #pragma once  
  2. #include"position.h"  
  3. #include"L_Queue.h"  
  4. //以下参数配置在头文件中会更好,在这里不做麻烦了。  
  5. const int offset_num = 4;  
  6. const int total_row = 8;//模拟矩阵的总行数  
  7. const int total_col = 8;//列数  
  8.   
  9. const int start_row = 1;//起始行值  
  10. const int start_col = 1;//起始列值  
  11.   
  12. const int finish_row = 6;//终止行值 此为数组下标值所以最大为total_row-1  
  13. const int finish_col = 3;//终止列值最大为total_col-1  
  14.   
  15. //const Position start(start_row,start_col);//起始位置  
  16. //const Position finish(finish_row,finish_col);//终止位置  
  17. class DB//电路布线  
  18. {  
  19. private:  
  20.     Position offset[offset_num];//四个移动方向  
  21.     int grid[total_row][total_col];//一个模拟方格的矩阵  
  22.     Position here;//当前矩阵位置  
  23.     Position neighbour;//当前矩阵的可能的邻居位置  
  24.     Position start;//布线开始位置  
  25.     Position finish;//布线结束位置  
  26.     Position *path;//存储的最短路径动态数组  
  27.     int path_length;//最短路径步数  
  28.     Queue<Position> qu_pos;//装载位置的队列 靠此遍历方格  
  29.   
  30.     bool FindPath();//封装 寻求路径算法  
  31. public:  
  32.     DB();  
  33.     ~DB();  
  34.     void output();//对外 调用接口  
  35.   
  36. };  
[cpp]  view plain copy
  1. #include"电路布线.h"  
  2. #include<iostream>  
  3. #include<fstream>  
  4. using namespace std;  
  5. //初始化 一些数据  
  6. DB::DB()  
  7. {  
  8.     ifstream in_grid("GRID.txt");  
  9.     for(int r=0;r<total_row;r++)  
  10.     {  
  11.         for(int c=0;c<total_col;c++)  
  12.             in_grid>>grid[r][c];  
  13.     }  
  14.     in_grid.close();  
  15.   
  16.     offset[0].row = 0;offset[0].col = 1;//右  
  17.     offset[1].row = 1;offset[1].col = 0;//下  
  18.     offset[2].row = 0;offset[2].col = -1;//左  
  19.     offset[3].row = -1;offset[3].col = 0;//上  
  20.   
  21.     start.row = start_row;start.col = start_col;//布线开始  
  22.     finish.row = finish_row;finish.col = finish_col;//结束  
  23.   
  24. }  
  25. DB::~DB()  
  26. {}  
  27. void DB::output()  
  28. {  
  29.     for(int r=0;r<total_row;r++)  
  30.     {  
  31.         for(int c=0;c<total_col;c++)  
  32.             cout<<grid[r][c]<<" ";  
  33.   
  34.         cout<<endl;  
  35.     }  
  36.     cout<<start.row<<" "  
  37.         <<start.col<<endl;  
  38.     cout<<finish.row<<" "<<finish.col<<endl;  
  39.   
  40.     cout<<endl<<endl;  
  41.     if(FindPath())  
  42.     {  
  43.         for(int i=0;i<path_length;i++)  
  44.             //cout<<path[i].row<<" "<<path[i].col<<endl;  
  45.             cout<<path[i]<<endl;  
  46.     }  
  47.     for(int r=0;r<total_row;r++)  
  48.     {  
  49.         for(int c=0;c<total_col;c++)  
  50.             cout<<grid[r][c]<<" ";  
  51.   
  52.         cout<<endl;  
  53.     }  
  54.     cout<<"路径步数:"<<path_length<<endl;  
  55. }  
  56. //布线 算法  
  57. bool DB::FindPath()  
  58. {  
  59.     if(finish == start)  
  60.     {  
  61.         path_length = 0;//路径步数 为0  
  62.         return true;//返回真  
  63.     }  
  64.     here.row = start.row; here.col = start.col;//把开始位置 标记为当前位置  
  65.     grid[start.row][start.col] = 2;//把开始位置 定为2 因为矩阵中0表示通路1表示堵塞  
  66.     while(true)//靠此 无限循环把整个矩阵都赋上路径值 如果可以的情况下  
  67.     {  
  68.         for(int i=0;i<offset_num;i++)//此循环 为了把当前的四个邻居中的可以的位置都进队列  
  69.         {  
  70.             neighbour.row = here.row + offset[i].row;  
  71.             neighbour.col = here.col + offset[i].col;//试探下一个位置  
  72.             if(grid[neighbour.row][neighbour.col] == 0)//该试探位置可行  
  73.             {  
  74.                 grid[neighbour.row][neighbour.col] = grid[here.row][here.col] +1;//路径值 +1  
  75.                 if(neighbour.row == finish.row && neighbour.col == finish.col)//该试探是结束位置  
  76.                     break;  
  77.                 qu_pos.In_Queue(neighbour);//把试探位置进队列  
  78.             }  
  79.         }//if条件右括号  
  80.         //第一个break之后 再次判断是否到达finish  
  81.         if(neighbour.row == finish.row && neighbour.col == finish.col)  
  82.             break;  
  83.         if(qu_pos.isEmpty() == true)  
  84.             return false;//如果第一次四次循环之后还是队列无元素 则说明无法到达布线终点  
  85.   
  86.         here = qu_pos.De_Queue();//把试探成功后进队列的元素取出赋给了当前的here  
  87.   
  88.     }//while循环右括号  
  89.   
  90.     //跳出大循环之后 构造路径  
  91.     path_length = grid[neighbour.row][neighbour.col] - 2;//实际的路径长度(因为之前在起始位置 有+2)  
  92.     path = new Position[path_length];//动态开辟路径长度空间  
  93.     here = finish;//把终点赋给当前值 开始反向寻找最小路径  
  94.     for(int j=path_length-1;j>=0;j--)  
  95.     {  
  96.         path[j] = here;//记下当前位置  
  97.         for(int i=0;i<offset_num;i++)  
  98.         {  
  99.             neighbour.row =here.row + offset[i].row;  
  100.             neighbour.col = here.col + offset[i].col;//到达 临近位置  
  101.               
  102.             if(grid[neighbour.row][neighbour.col] == j+2)  
  103.                 break;  
  104.         }//内层for循环右括号  
  105.   
  106.         here = neighbour;  
  107.   
  108.     }//外层for循环右括号  
  109.   
  110.     return true;  
  111.   
  112. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值