标签:
Time Limit: 1000MS
Memory Limit: 10000K | ||
Total Submissions: 2738 | Accepted: 1777 |
Description
Input
Output
Sample Input
3
6 6
1 3 1 3 1 3
3 1 3 1 3 1
4 4
1 1 3 3
1 1 3 3
12 11
1 2 3 3 2 4 1 5 1 3 5 10
3 1 2 3 2 4 12 1 5 5 3
Sample Output
6
0
8
Source
两个交叉的匹配为一组,每找到一组可行的匹配,答案数+2 。
设:f[上方匹配位置][下方匹配位置]=最优解
假设现在扫到了上方数组的i点和下方数组的j点。首先可以想到如果没有新的匹配,f[i][j]=max(f[i][j-1],f[i-1][j])
接着考虑新的匹配,在上方数组中从i往前找,找到最近的pos1使a[pos1]=b[j],同理在下方找到b[pos2]=a[i],那么pos1-j,pos2-i两条连线必然交叉,得到动归方程:
f[i][j]=max(f[i][j],f[pos1-1][pos2-1]+2)
1 /**/ 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 const int mxn=120; 9 int n1,n2; 10 int a[mxn],b[mxn]; 11 int f[mxn][mxn]; 12 int main(){ 13 int T; 14 scanf("%d",&T); 15 int i,j; 16 while(T--){ 17 memset(f,0,sizeof f); 18 scanf("%d%d",&n1,&n2); 19 for(i=1;i<=n1;i++)scanf("%d",&a[i]); 20 for(i=1;i<=n2;i++)scanf("%d",&b[i]); 21 for(i=1;i<=n1;i++) 22 for(j=1;j<=n2;j++){ 23 f[i][j]=max(f[i][j-1],f[i-1][j]); 24 if(a[i]==b[j])continue; 25 int k=i-1; 26 while(k && a[k]!=b[j])k--;int pos1=k; 27 k=j-1; 28 while(k && b[k]!=a[i])k--;int pos2=k; 29 if(pos1&&pos2) f[i][j]=max(f[i][j],f[pos1-1][pos2-1]+2); 30 } 31 printf("%d\n",f[n1][n2]); 32 } 33 return 0; 34 }
标签:
原文地址:http://www.cnblogs.com/SilverNebula/p/5737904.html