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; }