| 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;
}
poj 1692 Crossed Matchings(DP)
原文:http://blog.csdn.net/greenhandcgl/article/details/51357511