EOJ:Crossed Matchings
——给两行数字,在上下两行相同的数字间画条线,要求每条线必须要与且只能与另外一条线相交,一个数只能连一条线。问最多能连几条线。
——类似LCS 最长公共子序列。
——url:http://202.120.106.94/onlinejudge/problemshow.php?pro_id=504
——————————————————————————————————————————————————
参考最长公共子序列
DP[I][J]表示匹配到上边第I个和下面第J个时最多的线的条数
若A[I]==B[J]显然不能匹配(因为需要与另外条相交)则DP[I][J]=MAX(DP[I][J-1],DP[I-1][J-1])
否则DP[I][J]=MAX(DP[I-1][J],DP[I][J-1],DP[K][L]+2) A[K]==B[I],A[I]==B[L]
#include<stdio.h>
#include<memory.h>
#define N 105
int dp[N][N], a[N], b[N];
int cas, n, m, i, j, k, l;
int max(int a, int b)
{
return a > b ? a : b;
}
int main()
{
scanf("%d", &cas);
while (cas--)
{
memset(dp, 0, sizeof(dp));
scanf("%d%d", &n, &m);
for (i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (i = 1; i <= m; i++)
scanf("%d", &b[i]);
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (a[i] != b[j])
{
for (k = i - 1; k > 0; k--)
if (a[k] == b[j])
break;
for (l = j - 1; l > 0; l--)
if (b[l] == a[i])
break;
if (k>0&&l>0)
dp[i][j] = max(dp[i][j], dp[k - 1][l - 1] + 2);
}
}
printf("%d\n", dp[n][m]);
}
return 0;
}
浙公网安备 33010602011771号