题目大意:给定两组数字,求这两组数的最大匹配对数,即两个数相等就连一条线。
匹配的连线需要交叉,一个数字匹配过后不能再次匹配
解题思路:动态规划。
dp[i][j]表示,第一组数前i个与第二组数前j个的最大匹配数。
那么dp[i][j] = max(dp[i-1][j-1], dp[i-1][j], dp[i][j-1], dp[k1][k2] + 2)
k1,k2表示
当num1[i] != num2[j]时,
求出的num1[k1] == num2[j] , num1[i] == num2[k2];
k1 > 1, k2 > 1
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 110;
int m, n1, n2;
int dp[maxn][maxn], num1[maxn], num2[maxn];
int main()
{
scanf("%d", &m);
while(m-- != 0)
{
scanf("%d %d", &n1, &n2);
for(int i = 1; i <= n1; i++)
scanf("%d", &num1[i]);
for(int i = 1; i <= n2; i++)
scanf("%d", &num2[i]);
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n1; i++)
{
for(int j = 1; j <= n2; j++)
{
dp[i][j] = max(dp[i - 1][j - 1], dp[i][j - 1]);
dp[i][j] = max(dp[i][j], dp[i-1][j]);
if(num1[i] != num2[j])
{
int k1, k2;
for(k1 = i - 1; k1 >= 1; k1--)
{
if(num1[k1] == num2[j])
break;
}
for(k2 = j - 1; k2 >= 1; k2--)
{
if(num1[i] == num2[k2])
break;
}
if(k1 >= 1 && k2 >= 1)
dp[i][j] = max(dp[i][j], dp[k1 - 1][k2 - 1] + 2);
}
}
}
printf("%d\n", dp[n1][n2]);
}
return 0;
}