题意:两个序列,要选出交叉线,使得线的两点数字要相同,并且两条线两边的数字不能相同,问最多能弄出几组
思路:类似LCM,dp[i][j]表示两个i, j的方案,然后如果a[i] != b[j], 那么从i和j分别往前找到一个相同dp[i][j] = dp[k1][k2] + 2,剩下的转移就是dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 105;
int t, n, m, a[N], b[N], dp[N][N];
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++)
scanf("%d", &b[i]);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (a[i] == b[j]) continue;
int k1, k2;
for (k1 = i - 1; k1; k1--)
if (a[k1] == b[j]) break;
for (k2 = j - 1; k2; k2--)
if (b[k2] == a[i]) 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;
}