COGS597 交错匹配

版权声明:蒟蒻的原创,转载请注明出处,附上链接。 https://blog.csdn.net/qq_39670434/article/details/79965029

题意

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

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

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

题解

先设出状态把。

f[i][j]aibj

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

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

这里为什么一定是最靠后的呢?
因为我们可以显然发现,若i>kj>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;
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页