堆栈应用(四):开关盒布线

1、问题描述

开关盒布线问题是这样的:给定一个矩形布线区域,其外围有若干针脚。两个针脚之间通过布设一条金属线路而实现互连。这条线路被称为电线,被限制在矩形区域内。如果两条电线发生交叉,则会发生电流短路。所以,不允许电线间的交叉。每对互连的针脚被称为网组。我们的目标是要确定对于给定的网组,能否合理地布设电线以使其不发生交叉。图 5-7a 给出了一个布线的例子,其中有八个针脚和四个网组。四个网组分别是 ( 1 , 4 , ), ( 2 , 3 ), ( 5 , 6 )和( 7 , 8 )。图5 -7b 给出的布线方案有交叉现象发生( (1,4) 和(2,3) 之间),而图 5-7c 则没有交叉现象发生。由于四个网组可以通过合理安排而不发生交叉, 因此可称其为可布线开关盒( routable switch box)。我们要解决的问题是,给定一个开关盒布线实例,确定它是不是一个可布线的。




2、解决思路

  为了解决开关盒布线问题,我们注意到,当两个针脚互连时,其电线把布线区分成两个分区。例如,当 ( 1 , 4 )互连时,就得到了两个分区,一个分区包含针脚 2和3,另一个分区包含针脚5 ~ 8。现在如果有一个网组,其两个针脚分别位于这两个不同的分区,那么这个网组是不可以布线的,因而整个电路也是不可布线的。如果没有这样的网组,则可以继续判断每个独立的分区是不是可布线的。为此,可以从一个分区中取出一个网组,利用该网组把这个分区又分成两个子分区,如果任一个网组的两个针脚都分布在同一个子分区之中(即不会出现两个针脚分别位于两个子分区的情形),那么这个分区就是可布线的。
为了实现上述策略,可以按顺时针或反时针方向沿着开关盒的外围进行遍历,可从任意一个针脚开始。例如,如果按顺时针方向从针脚 1 开始遍历图 5-7a 中的针脚,那么将依次检查针脚1, 2, ..., 8。针脚1 和4属于同一个网组,那么在针脚 1至针脚4之间出现的所有针脚构成了第一个分区,而在针脚 4至针脚 1 之间出现的所有针脚构成了第二个分区。把针脚 1 放入堆栈,然后继续处理,直至遇到针脚 4。这个过程使我们仅在处理完一个分区之后才能进入下一个分区。下一个针脚是针脚 2,它与针脚 3同属一个网组,它们又把当前分区分成两个子分区。与前面的做法一样,把针脚2放入堆栈,然后继续处理直至遇到针脚3。由于针脚3与针脚2属同一个网组,而针脚2正处在栈顶,这表明已经处理完一个子分区,因此可将针脚 2从栈顶删除。接下来将到针脚4,由于与之互连的针脚 1正处在栈顶,因此当前的分区已经处理完毕,可从栈顶删除针脚1 。按照这种方法继续进行下去,直至检查完八个针脚,堆栈变空,所创建的分区都已处理完毕为止。

  而对于不可布线的开关盒,最后堆栈不会为空。

3、代码实现

堆栈的实现见:堆栈的链表方式实现

 1 #include "Checkbox.h"
 2 //net存储开关盒针脚的分组编号,n为针脚个数
 3 bool CheckBox(int net[],int n)
 4 {
 5     LinkedStack<int> S;
 6     if (n<=0)
 7     {
 8         throw OutofBounds();
 9     }
10 
11     for (int i = 0; i < n;++i)
12     {
13         if (S.IsEmpty())
14         {
15             S.Add(net[i]);//堆栈为空,直接添加
16             continue;
17         }
18 
19         if (S.Top()==net[i])//等于栈顶,说明可以直接走线
20         {
21             int temp;
22             S.Delete(temp);
23         }
24         else
25         {
26             S.Add(net[i]);
27         }
28     }
29 
30     return S.IsEmpty();//堆栈空说明无交叉可布线
31 }
 1 #include "Checkbox.h"
 2 #include <istream>
 3 
 4 int main()
 5 {
 6     int net[] = { 1, 2, 3, 2, 1, 3, 4, 4 };    
 7 
 8     if (CheckBox(net, 8))
 9     {
10         std::cout << "可布线开关盒" << std::endl;
11     }
12     else
13     {
14         std::cout << "不可布线开关盒" << std::endl;
15     }
16 
17     system("pause");
18 
19     return 0;
20 }

输出:

原文地址:https://www.cnblogs.com/haoliuhust/p/4262550.html