题目描述 Description
给出两个1~N的随机排列A,B。若Ai=Bj,则你可以在Ai,Bj之间连一条线。要求每条线至多与一条线相交。下图分别说明了一种合法和不合法的方案。
输入描述 Input Description
第一行一个正整数N。
接下来一行N个正整数,描述A。
接下来一行N个正整数,描述B。
输出描述 Output Description
输出一行一个整数,描述答案(最大合法连线数量)。
样例输入 Sample Input
7
1 5 7 3 2 6 4
7 3 4 1 6 5 2
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
测试点编号 数据范围
1,2,3 N≤20
4,5,6,7,8,9,10 N≤1000
分类标签 Tags 点此展开
AC代码:
/* 设f[i][j]表示取序列A前i个元素与序列B前j个元素的最多连线数量,则有如下状态转移方程: (1)A[i]=B[j] f[i][j]=f[i-1][j-1]+1 (2)A[i]≠B[j] f[i][j]=max(f[X][Y]+2,f[i-1][j],f[i][j-1])(X表示B[j]在序列A中的位置,Y与此同理)。 此类型的DP似乎可以用前n项来二维实现。 */ #include<cstdio> #include<algorithm> using namespace std; const int N=1e3+1; int n,a[N],b[N],pa[N],pb[N],f[N][N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),pa[a[i]]=i;//位置数组 for(int i=1;i<=n;i++) scanf("%d",&b[i]),pb[b[i]]=i; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1; else{ f[i][j]=max(f[i-1][j],f[i][j-1]); if(pa[b[j]]<i&&pb[a[i]]<j) f[i][j]=max(f[i][j],f[pa[b[j]]][pb[a[i]]]+2); } } } printf("%d",f[n][n]); return 0; }