电路布线
参考
链接:🖇️https://blog.csdn.net/vangoudan/article/details/106413539
题目
简化问题
实际就是求最大不相交线
分析问题
递推分析
- 当i=1时,j<n(i)。代表的是与第一个点相连的前无效边,那么他们的size就是0,因为size是:第一层内不相交的有效边的最多个数
- 当i=1时,j>=n(i)。当j=n(i)的时候,代表N(i,j)就是有效边了,此时是第一条有效边,不用顾虑其他,将这条边加入到第一层中,也就是size=1;当j>n(i)的时候,代表N(i,j)为后无效边,他的影响不了size的大小,所以size还是1。
- 当i>1时,j<n(i)的时候,代表着是与第i个点相连的前无效边,此时的N(i,j)的size依赖于N(i-1,j)的size,我们用反证法来证明:
如果size(i,j)!=size(i-1,j),那么就有size(i,j)>size(i-1,j)或者size(i,j)<size(i-1,j)
size(i,j)>size(i-1,j),当我们要让size(i,j)>size(i-1,j)的时候,代表着我们要有一条新的有效边加入,但是题目中j<n(i),此时的边都为无效边,没有有效边,与条件不符。
size(i,j)<size(i-1,j),这个显然不可能,没加边就不错了,还能减边?
- 当i>1时,j>=n(i)的时候。当j=n(i)的时候,也就是N(i,j)为有效边时,我们考虑两方面:
- 这个有效边可以放进第一层
- size[i][j] = size[i - 1][pi[i] - 1] + 1
- 这个有效边不可以放进第一层。
- size[i][j] = size[i - 1][j]。和之前的情况一样
- 这个有效边可以放进第一层
理解
变量说明
size[i][j]:上下端分别有 i 个和 j 个接线柱的电路板的第一层最大不相交连接数,代表的是区域
比如i是1,j是9,最大不相交连接数是1,有(1,8)
pi[i]:π(i),下标从 1 开始
例子说明
代码实现
#include<stdio.h>
#define N 10 //问题规模
int m = 0;//记录最大连接集合中的连接柱
/*求最大不相交连接数*/
void mainNum(int pi[],int size[N+1][N+1],int n){
int i,j;
/*当j<π(1)时*/
for(j=0;j<pi[i];j++) size[1][j]=0;
/*当j>=π(1)时*/
for(j=0;j<pi[i];j++) size[1][j]=1;
for (i = 2; i < n; i ++) {
for (j = 0; j < pi[i]; j ++ ) size[i][j] = size[i-1][j]; /* 当 j < pi[i]时 */
for (j = pi[i]; j <= n; j ++ ) {
/* 当 j >= c[i]时,考虑两种情况 */
size[i][j] = size[i-1][j] >= size[i - 1][pi[i] - 1] + 1? size[i-1][j] : size[i - 1][pi[i] - 1] + 1;
}
}
/* 最大连接数 */
size[n][n] = size[n - 1][n] >= size[n - 1][pi[n] - 1] + 1
? size[n - 1][n] : size[n-1][pi[n]-1]+1;
}
Nets求解
求最大不交集
void constructSet(int pi[], int size[N + 1][N + 1], int n, int net[n]) {
int i, j = n;
m = 0;
for (i = n; i > 1; i -- ) {
/* 从后往前 */
/* (i, pi[i])是最大不相交子集的一条连线 */
if (size[i][j] != size[i - 1][j]) {
net[m++] = i ; /* 将 i 记录到数组 net 中,连接线数自增 1 */
j = pi[i] - 1; /* 更新扩展连线柱区间 */
}
}
if (j >= pi[1]) net[m ++ ] = 1; /* 当 i = 1 时 */
}