电路布线
在一块电路板的上、下两端分别有n个接线柱。根据电路设计,要求用导线(i,π(i))将上端接线柱i与下端接线柱π(i)相连,如图所示。
其中,π(i),1<=i<=n是{1,2,…,n}的一个排列。导线(i,π(i))称为该电路板上的第i条连线。对于任何1<=i π(j)。
在制作电路板时,要求将这n条连线分布到若干绝缘层上。在同一层上的连线不相交。你的任务是要确定将哪些连线安排在第一层上,使得该层上有尽可能多的连线。换句话说,就是确定导线集Nets={ i,π(i),1<=i<=n}的最大不相交子集。
今天看书实在看不下去,闲得无聊随手拿了本算法书以乱心智。心烦地的乱翻,最后停在了这道题目上。一开始没有看题解,一通胡思乱想之后,设法证明自己的想法是正确,结果失败了。这里的失败是说未能给证明,并不是指我算法的正确与否。回来调试,又是几个小case错误外。。。上网一搜,网上的文章一大抄,都是书的一样的算法(见附录)。。。。
思想来源上次看到的一道题目: 谁看的最多。
算法思想:
。。。。懒得写,迟点再写。。。
隐约地觉得算法是正确的。但是,现在还没有证明。其实更隐约地觉得其实我的思路里已经蕴含了它的思想。。。
1 #include<iostream>
2 #include<malloc.h>
3
4 using namespace std;
5
6 int func17(int b[], int n)
7 {
8 int *c; //c[i]记录上排线0到i-1中的连线不相交的最大集合
9 int *d; //d[i]记录i阶段的选择 若无,则为-1
10 int bigpos; //当前最大值得下标, 若有相同的最大值,择选b[]小的
11 int i,j;
12
13 if (n<=0)
14 {
15 return 0;
16 }
17 c = (int *)malloc(sizeof(int)*n);
18 d= (int *)malloc(sizeof(int)*n);
19
20 c[0] =1;
21 d[0] = -1;
22 bigpos = 0;
23
24 for (i=0; i<n; i++)
25 {
26 for (j=bigpos; j!=-1;)
27 {
28 if (b[j] <b[i])
29 {
30 break;
31 }
32 else
33 {
34 j = d[j];
35 }
36 }
37 if (j==-1)
38 {
39 c[i] =1;
40 d[i] =-1;
41
42 }
43 else
44 {
45 c[i] = c[j]+1;
46 d[i] = j;
47 }
48 if (c[i]> c[bigpos] || (c[i]==c[bigpos] && b[i]<b[bigpos]))
49 {
50 bigpos = i;
51 }
52 }
53
54 int tmp = c[bigpos];
55
56 free(c);
57 free(d);
58
59 return tmp;
60 }
61
62 int main()
63 {
64 int a[] = {8,7,4,2,5,1,9,3,10};
65
66 cout<<func17(a, sizeof(a)/sizeof(int))<<endl;;
67
68 return 0;
69 }
附录:
问题分析:
1. 最优子结构性质
记N(i,j) = {t|(t, π(i)) ∈ Nets,t ≤ i, π(t) ≤ j }. N(i,j)的最大不相交子集为MNS(i,j)。Size(i,j)=|MNS(i,j)|。
1) 当i = 1时
2) 当i >1时,
① j <π(i)。此时,(i,π(i)) 不属于N(i,j)。故在这种情况下,N(i,j) = N(i-1,j),从而Size(i,j)=Size(i-1,j).
② j ≥π(i)。此时,若(i, π(i))∈MNS(i,j),则对任意(t, π(i))∈MNS(i,j)有t < i且π(t)< π(i);否则,(t, π(t))与(i, π(i))相交。在这种情况下MNS(i,j)-{(i, π(i))}是N(i-1, π(i)-1)的最大不相交子集。否则,子集MNS(i-1, π(i)-1)∪{(i, π(i))}包含于N(i,j)是比MNS(i,j)更大的N(i,j)的不相交子集。这与MNS(i,j)的定义相矛盾。
若(i, π(i))不属于MNS(i,j),则对任意(t, π(t))∈MNS(i,j),有t<i。从而MNS(i,j)包含于N(i-1,j),因此,Size(i,j)≤Size(i-1,j).
另一方面,MNS(i-1,j)包含于N(i,j),故又有Size(i,j) ≥Size(i-1,j),从而Size(i,j)= Size(i-1,j).
2. 递归计算最优值
经以上后分,可电路布线问题的最优值为Size(n,n)。由该问题的最优子结构性质可知:
毕