一:问题重述
在一块电路板上下两端分别有n个接线柱。根据电路设计,要求用导线(i,tail(i))将上端接线柱i与下端接线柱tail(i)相连,其中,tail(i),1<=i<=n是{1,2,....,n}的一个排列。导线(i,tail(i))称为该电路板上的第i条连线。对于任何1<=i<j<=n,第i条连线和第j条连线相交的充分且必要条件是tail(i)>tail(j)。在制作电路板是,要求将这n条连线分布到若干绝缘层上,使得该层上有尽可能多的连线。换句话说,该问题就是确定导线集Nets={(i,tail(i)),1<=i<=n}的最大不相交集。。
二:最优子结构性质
记N(i,j)={t|(t,tail(t))∈Nets,t<=i,tail(i)<=j},N(i,j)的最大不相交子集为MNS(i,j),Size(i,j)=|MNS(i,j)|。
(1)当i=1时,
如果j<tail(1),MNS(i,j)=N(1,j)=空集
如果j>=tail(1),MNS(i,j)=N(1,j)={(1,tail(1))}
(2)当i>1时,
➀j<tail(i)。此时,(i,tail(i))∉N(i,j)。故再这种情况下,N(i,j)=N(i-1,j),从而Size(i,j)=Size(i-1,j)。
➁j>=tail(i)。
若(i,tail(i))∈MNS(i,j),则对任何(t,tail(t))∈MNS(i,j)有t<j且tail(t)<tail(i)。否则,(t,tail(t))与(i,tail(i))相交。
若(i,tail(i))∉MNS(i,j),则对任何(t,tail(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)。
综上可知。电路布线问题满足最优子结构。。
三:递归表达式:
(1)i=1,
j<tail(1), Size(i,j)=0;
j>=tail(1),Size(i,j)=1;
(2)i>1
j<tail(1),Size(i,j)=Size(i-1,j)
j>=tail(1),Size(i,j)=max{Size(i-1,j),Size(i-1,tail(i)-1)+1}
四:代码如下:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int tail[100];//记录下方与坐标相连的点
int size[100][100];//从上方i点到下方j点之间最大不相交集合
int nets[100];//记录最大不相交集合
void init(int n)
{
for(int i=1;i<=n;i++)
{
cin>>tail[i];
}
}
void MNS(int n)
{
for(int i=1;i<tail[1];i++)
{
size[1][i]=0;
}
for(int i=tail[1];i<=n;i++)
{
size[1][i]=1;
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<tail[i];j++)
{
size[i][j]=size[i-1][j];
}
for(int j=tail[i];j<=n;j++)
{
size[i][j]=max(size[i-1][j],size[i-1][tail[i]-1]+1);
}
}
}
int traceback(int n)
{
int j=n;
int m=0;
for(int i=n;i>1;i--)
{
if(size[i][j]!=size[i-1][j])
{
nets[++m]=i;j=tail[i]-1;
}
}
if(j>=tail[1])nets[++m]=1;
return m;
}
void out(int m)
{
for(int i=m;i>=1;i--)
{
cout<<nets[i]<<" ";
}
cout<<endl;
}
int main()
{
int n;
cin>>n;
init(n);
MNS(n);
int m=traceback(n);
out(m);
return 0;
}