zoukankan      html  css  js  c++  java
  • 【cogs 597】【dp】交错匹配

    597. 交错匹配

    ★☆   输入文件:crossa.in   输出文件:crossa.out   简单对照
    时间限制:1 s   内存限制:128 MB
    

    【问题描写叙述】

    有两行自然数。 UP[1..N] 。 DOWN[1..M] 。假设UP[I]=DOWN[J]=K 。那么上行的第 I 个位置的数就能够跟下行的第 J 个位置的数连一条线,称为一条 K 匹配,可是 同一个位置 的数最多仅仅能连一条线。另外,每个 K 匹配都 必须且至多 跟一个 L 匹配相交且 K ≠ L !

    如今要求一个最大的匹配数。

    【输入格式】

    第一行有两个正整数 N 和 M 。

    第二行 N 个 UP 的自然数。第三行 M 个 DOWN 的自然数。
    当中

    0<N。M<=200, UP、DOWN 的数都不超过 32767 。

    【输出格式】

    最大匹配数 。

    【输入输出例子1】

    输入:
    crossa.in

    12 11
    1 2 3 3 2 4 1 5 1 3 5 10
    3 1 2 3 2 4 12 1 5 5 3
    

    输出:
    crossa.out

    8
    

    【输入输出例子2】

    输入:
    crossa.in

    4 4
    1 1 3 3
    1 1 3 3
    

    输出:
    crossa.out

    0
    

    题解:

    题意略坑。分析例子能够发现事实上是要求 满足每条上下连边(i到j连边条件是a[i]==b[j])都有且仅仅有还有一条连边与之相交 的最多边数。
    于是能够dp。f[i][j]表示在a[i],b[j]前满足条件的最大边数。


    考虑转移,首先每个状态f[i][j]都是有上两个状态转移来,即

    f[i][j]=max(f[i-1][j],f[i][j-1])
    

    然后当前状态是能够由一个新连边状态来尝试更新的,即

    f[i][j]=max(f[i][j],f[x-1][y-1]+2)(x,y是新连边状态的位置)
    

    Code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,m,ans=0,a[310]={0},b[310]={0},f[310][310];
    int in(){
        int x=0; char ch=getchar();
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    int last(int c[],int w,int k){
        for (int i=w-1; i>=1; i--)
            if (c[i]==k) return i;
        return 0;
    }
    void dp(){
        f[0][0]=f[0][1]=f[1][0]=0;
        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;
                x=last(a,i,b[j]);
                y=last(b,j,a[i]);
                if (x>0 && y>0)
                    f[i][j]=max(f[i][j],f[x-1][y-1]+2);
            }
        ans=f[n][m];
    }
    int main(){
        n=in(),m=in();
        for (int i=1; i<=n; i++) a[i]=in();
        for (int i=1; i<=m; i++) b[i]=in();
        dp();
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    程序员必备工具之Cmder
    Markdown简明教程
    几种黑灰名词解释
    windows下 mysql启动错误1067进程意外终止
    Mac OS 安装redis
    java里的这些
    maven 两条命令建立 web项目
    判断StringBuilder是否为空
    map与list的交集、补集操作
    关于创业
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7044924.html
Copyright © 2011-2022 走看看