COGS597 交错匹配

题意

题意就是给出两个数列a和b,一个交错匹配是这样:

a [ i ] = b [ j ] ! = a [ k ] = a [ l ] ( i < k j > l )

如果匹配之后连了线,交叉能且只能出现一次。
求出这两个数列最大的匹配数。

题解

先设出状态把。

f [ i ] [ j ] a i b j

显然每次我们都要判断a[i]和b[j]是否和前面的数形成一个交错匹配。
如果 不形成匹配,那么就
f [ i ] [ j ] = m a x ( f [ i 1 ] [ j ] , f [ i ] [ j 1 ] )

如果 形成匹配,假设数列 a 中和 b [ j ] 匹配的数的位置最靠后的是 x ,数列 b 中和 a [ i ] 匹配的数的位置最靠后的是 y ( x < i         y < j )
那么就有
f [ i ] [ j ] = f [ x 1 ] [ y 1 ] + 2

这里为什么一定是最靠后的呢?
因为我们可以显然发现,若 i > k j > l ,则有 f [ k ] [ l ] f [ i ] [ j ]
那么就ok了。

code

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int num=0;
    bool flag=true;
    char c=' ';
    for(;c>'9'||c<'0';c=getchar())
        if(c=='-')
            flag=false;
    for(;c>='0'&&c<='9';num=num*10+c-48,c=getchar());
    return flag ? num : -num;
}
const int maxn=210;
int n,m,a[maxn],b[maxn];
void init()
{
    n=read();
    m=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=1;i<=m;i++)
        b[i]=read();
}
int f[maxn][maxn];
void DP()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f[i][j]=max(f[i-1][j],f[i][j-1]);
            if(a[i]!=b[j])
            { 
                int ti,tj;
                for(ti=i;ti>=1;ti--)
                    if(a[ti]==b[j])break;
                for(tj=j;tj>=1;tj--)
                    if(b[tj]==a[i])break;
                //找到最靠后的匹配位置 
                if(ti!=0&&tj!=0)
                    f[i][j]=max(f[i][j],f[ti-1][tj-1]+2);
            }
        }
    printf("%d\n",f[n][m]);
}
int main()
{
    init();
    DP();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39670434/article/details/79965029