電路佈線問題

電路佈線問題

   製作電路板時,將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; 
} 


發佈了161 篇原創文章 · 獲贊 70 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章