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

  

posted on 2011-08-09 23:34  风也轻云也淡  阅读(184)  评论(0编辑  收藏  举报