• POJ 1692 DP


    题意:

    题意:给出两行数,求上下匹配的最多组数是多少。
    匹配规则
    1,匹配对的数字必须相同
    2.每个匹配必须有且只能有一个匹配与之相交叉,且相交叉的两组匹配数字必须不同
    2,一个数最多只能匹配一次

    思路:

    其实凭感觉瞎写呗。类似于最长公共子序列的方程。

    dp[i][j]=max(dp[i-1][j-1],dp[i-1][j],dp[i][j-1],dp[pi-1][pj-1]+2)  表示前a的前i个数和b的前j个数匹配的最大值

    依次含义分别是:i,j都不匹配;i不参与匹配;j不参与匹配,i,j和前面的某个符合要求的字符匹配

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream> 
     5 
     6 #define N 120
     7 
     8 using namespace std;
     9 
    10 int lena,lenb,a[N],b[N],dp[N][N],tt;
    11 
    12 void read()
    13 {
    14     scanf("%d%d",&lena,&lenb);
    15     for(int i=1;i<=lena;i++) scanf("%d",&a[i]);
    16     for(int i=1;i<=lenb;i++) scanf("%d",&b[i]);
    17 }
    18 
    19 void go()
    20 {
    21     memset(dp,0,sizeof dp);
    22     for(int i=1,pi,pj;i<=lena;i++)
    23         for(int j=1;j<=lenb;j++)
    24         {
    25             dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    26             dp[i][j]=max(dp[i][j],dp[i-1][j-1]);
    27             pi=0; pj=0;
    28             for(int k=j-1;k>=1;k--)
    29                 if(a[i]==b[k]) {pj=k;break;}
    30             for(int k=i-1;k>=1;k--)
    31                 if(b[j]==a[k]) {pi=k;break;}
    32             if(pi&&pj&&a[i]!=b[j]) dp[i][j]=max(dp[i][j],dp[pi-1][pj-1]+2);
    33         }
    34     printf("%d\n",dp[lena][lenb]);
    35 }
    36 
    37 int main()
    38 {
    39     scanf("%d",&tt);
    40     while(tt--)
    41     {
    42         read();
    43         go();
    44     }
    45     system("pause");
    46     return 0;
    47 }

    吐槽:

    今天抑郁了一整天,被后缀数组搞死了。。下标整死人啊。等冷静下来继续看,看完了我一定要写一份清晰易懂的分析,表示网上的后缀数组分析的让我这种弱智根本看不懂。。

    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    Linux基础命令---swapon
    Linux基础命令---fsck
    Linux基础命令---e2fsck
    Combination Sum
    Pow(x, n)
    Permutations
    Permutation Sequence
    Rotate List
    Unique Paths II
    Unique Paths
  • 原文地址:https://www.cnblogs.com/proverbs/p/2711167.html
Copyright © 2020-2023  润新知