Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2717 | Accepted: 1763 |
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
/* 题意:给出两行数,求上下匹配的最多组数是多少。 匹配规则 1,匹配对的数字必须相同 2.每个匹配必须有且只能有一个匹配与之相交叉,且相交叉的两组匹配数字必须不同 2,一个数最多只能匹配一次 方法:DP 分析:用dp[i][j]表示第一行取i个数,第二行取j个数字的最多匹配项 对于某个dp[i][j]: 1.不匹配第一行i个,或不匹配第二行第j个:dp[i][j]=Max(dp[i-1][j],dp[i][j-1]) 2.如果a[i]==b[j],不产生新匹配,匹配结果为1的值 3.若a[i]!=b[j]: a.则第一行从i往前扫,直到扫到第一个a[k1]==b[j](k1 b.同理,第二行从j往前扫,直到扫到第一个b[k2]==a[i](k2 若找不到这样的k1,k2则不能才产生新匹配,跳过 若存在这样的k1,k2,此时匹配(a[i],b[k2])、(a[k1],b[j])匹配, 才生新的匹配情形,匹配数量为:dp[k1-1][k2-1]+2. 最优dp[i][j]=Max(1,2,3); */ #include<cstdio> #include<cstdlib> #include <cstring> int dp[102][102]; int a[102],b[102]; int n,m; int max(int a,int b){//求ab中的较大值 return a>b?a:b; } int main(){ int i,j,t,k1,k2; scanf("%d",&t);//输入测试的组数 while(t--){ scanf("%d%d",&n,&m);//输入两个数字串的长度 for(i=1;i<=n;i++) scanf("%d",&a[i]); for(j=1;j<=m;j++) scanf("%d",&b[j]); memset(dp,0,sizeof(dp));//初始化 for(i=2;i<=n;i++) for(j=2;j<=m;j++){ dp[i][j]=max(dp[i-1][j],dp[i][j-1]);//选出前面最大的 if(a[i]!=b[j]){ for(k1=i-1;k1>=1;k1--) if(a[k1]==b[j])break; for(k2=j-1;k2>=1;k2--) if(a[i]==b[k2])break; if(k1&&k2) dp[i][j]=max(dp[i][j],dp[k1-1][k2-1]+2); } } printf("%d\n",dp[n][m]); } return 0; }