POJ1692 Crossed Matchings DP
Description
给出两列数,要求对上下相同的数进行连线,要求
1.一个数最多连一条线。
2.一条线必须且仅与一条线相交。
求最多可以连出几条线。
题解
这一题可以用LIS的思想来建立状态转移方程。
令f[i][j]表示第一行到i个数,第二行到j个数的答案。
f[i][j]=max(f[i][j−1],f[i−1][j])
如果能找到 x∈[1,i) 和 y∈[1,j) 满足 a[x]=b[j]b[y]=a[j] (就是上下匹配)
那么
f[i][j]=max(f[i][j−1],f[i−1][j],f[i−1][j−1]+2)
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define MAXN 100+10
using namespace std;
int f[MAXN][MAXN],a[MAXN],b[MAXN],t,n,m;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x,y;
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(a[i]==b[j]) continue ;
for(x=i-1;x>0;x--) if(a[x]==b[j]) break;
for(y=j-1;y>0;y--) if(b[y]==a[i]) break;
if(!x||!y) continue ;
f[i][j]=max(f[i][j],f[x-1][y-1]+2);
}
}
printf("%d\n",f[n][m]);
}
return 0;
}