电路布线问题

电路布线问题

   制作电路板时,将n条连线分布到若干绝缘层上。在同一层的连线不相交。电路布线问题就是要确定将哪些连线安排到第一层上,使该层上有尽可能多的连线。

  输入一个整数n代表接线柱的数量,输入n个数代表与上接线柱连接的下接线柱编号

样例输入

10
8 7 4 2 5 1 9 3 10 6

样例输出

4

解:

例如,给定如图的电路板。从10条连线中,选取不相交的最大连线集合。用a(i)=j表示要求上排的第i个接线柱要求接到下排的第 j 个接线柱。

  在图中,a(1)=8 , a(2)=7, a(1)=4, a(1)=2, a(1)=5, a(1)=1, a(1)=9, a(1)=3, a(1)=10, a(1)=6。


  如果使得(i , a[i])与(j , a[j])不相交,假设 j>I 则两条线不相交的充分必要条件为 a[j]>a[i]。在制作电路板时,要求将这n条连线分布到若干绝缘层上。在同一层上的连线不相交。电路布线问题要确定将哪些连线安排在第一层上,使得该层上有尽可能多的连线。换句话说,该问题要求确定所有导线集的最大不相交子集。

  记N(i,j){(t,a(t)) |  t<=i,a(t)<=j }代表上接线柱小于等于i并且下接线柱小于等于j的连线的集合。N(i,j)的最大不相交子集为MNS(i,j),假设MNS(i,j)中的连线数目为dp[i][j];
下面对MNS(i,j)进行判断区分:


(1) 当i = 1时

①如果j>=a[i],为了考虑更多的连线,则(i,a[i])应当在集合MNS(i,j) 中,即dp(i,j)=1;

②如果j<a[i],此时则(i,a[i])不应放在集合MNS(i,j) 中,即dp(i,j)=0


(2)当i >1时

j<ai)。

此时,(iai))不属于MNSij)。故在这时,MNSij =MNSi-1j),从而dpij=dpi-1j)。

j >=a(i)

  若(i, a(i))MNS(i,j),则对任意(t, a(t))MNS(i,j)t <ia(t)<a(i);否则,(t,a(t))(i,a(i))相交。在这种情况下MNS(i,j)-{(i,a(i))}N(i-1,a(i)-1)的最大不相交子集。否则,子集MNS(i-1,a(i)-1){(i,a(i))}包含于N(i,j)是比MNS(i,j)更大的N(i,j)的不相交子集。这与MNS(i,j)的定义相矛盾。

  (i, a(i))不属于MNS(i,j),则对任意(t, a(t))MNS(i,j),有t<i。从而MNS(i,j)包含于N(i-1,j),因此,dp(i,j)≤dp(i-1,j)另一方面,MNS(i-1,j)包含于N(i,j),故又有dp(i,j)≥dp(i-1,j),从而Sizei,j=Size(i-1,j)

ia[i])属于MNS(i,j),则dp(i,j)=dp(i-1,a[i])+1;


ia[i])不属于MNS(i,j),则dp(i,j)=dp(i-1,j);



所以递推公式:

1)当i=1时

(2)当i>1时

#include <stdio.h>
#include <string.h>

#define MAX(a, b) ((a)>(b)?(a):(b)) 

int main()
{
	int n;
	int a[100],dp[100][100];
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	} 
	memset(dp,0,sizeof(dp));
	for(int j=1;j<=n;j++) 
	{
		if(j<a[1])
			dp[1][j]=0;
		else
			dp[1][j]=1;
	}
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(j<a[i])
				dp[i][j]=dp[i-1][j];
			else
				dp[i][j]=MAX(dp[i-1][j],dp[i-1][a[i]-1]+1);
		}
	}
	
	printf("%d\n",dp[n][n]);
	return 0; 
} 


相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页