zoukankan      html  css  js  c++  java
  • zoj1425 Crossed Matchings

    【题意】:给你上下各一列数,让你进行匹配。规则是数字相同的才可以匹配,且每个数字只可以被匹配一次,并且匹配的时候一定要是两个匹配以线段相交的形式出现,且每组匹配只能有一个交点。再然后,还有一个限制条件,就是每组两个匹配的四个字符不能都是一样的。示意图戳开链接看。

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1425

    【分析】:这道题看起来有点像最长公共子序列。因为给的序列是两个线性的。所以,我们考察dpi][j]的状态。
    首先dp[i][j]分别表示串1和2分别处理到i和j位置是,能够得到的最大的匹配数。很不错的题目

    我们考虑dp问题的时候一定要考虑状态转移!!!!!

    当s1[i]和s2[j]失配的时候,那么一定是s1[i]和s2[1]----s2[j-1]的这些字符可能存在匹配,即dp[i][j-1]

                                        同样,s2[j]和s1[1]----s1[i-1]可能存在匹配,假设找到p2,即dp[i-1][j]

                                        那么,当s1[i]向前找到匹配的s2[p1],且当s2[j]向前找到匹配的s1[p2]时,且s1[i]!=s2[j]时,一定又找到了一对新的交叉线。

    所以://s1[i]!=s2[j]

    dp[i][j]=max(dp[i][j],dp[i-1][j]);
    dp[i][j]=max(dp[i][j],dp[i][j-1]);
    if(mati>0 && matj>0) dp[i][j]=max(dp[i][j],dp[matj-1][mati-1]+2);

    那么s1[i]==s2[j]时,若两点形成一条线,那么要找到交叉线一定是一个在[i,j]区间左,一个在右,那么不可能形成新的匹配。

    所以dp[i][j]=max(dp[i-1][j],dp[i][j-1]) 具体看代码

    【代码】:

     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 using namespace std;
     5 
     6 int dp[105][105];
     7 int N1,N2;
     8 int a[105],b[105];
     9 int main(){
    10     int M;
    11     scanf("%d",&M);
    12     while(M--){
    13         scanf("%d%d",&N1,&N2);
    14         for(int i=1;i<=N1;i++) scanf("%d",&a[i]);
    15         for(int i=1;i<=N2;i++) scanf("%d",&b[i]);
    16 
    17         memset(dp,0,sizeof(dp));
    18         for(int i=1;i<=N1;i++){
    19             for(int j=1;j<=N2;j++){
    20                 if (a[i]==b[j]) dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    21                 if (a[i]!=b[j]) {
    22                     int mati=-1,matj=-1;
    23                     for(int p=j-1;p>=1;p--){//在第二行搜索可能匹配的位置
    24                         if (b[p]==a[i]) {
    25                             mati=p;break;
    26                         }
    27                     }
    28                     for(int p=i-1;p>=1;p--){//在第一行搜索匹配b的位置
    29                         if (a[p]==b[j]){
    30                             matj=p;break;
    31                         }
    32                     }
    33                     dp[i][j]=max(dp[i][j],dp[i-1][j]);
    34                     dp[i][j]=max(dp[i][j],dp[i][j-1]);
    35                     if(mati>0 && matj>0) dp[i][j]=max(dp[i][j],dp[matj-1][mati-1]+2);
    36                 }
    37             }
    38         }
    39 
    40         cout<<dp[N1][N2]<<endl;
    41     }
    42     return 0;
    43 }
    View Code
  • 相关阅读:
    CMD命令点滴
    Android之Service的使用
    JavaScript第一章
    Android之BroadcastReceiver的使用
    Android之短信验证
    HTML学习(一)
    新一代联合国秘书长?
    粗茶淡饭
    Access里的Case效果 解决“IErrorInfo.GetDescription 因 E_FAIL(0x80004005) 而失败!”问题!
    利用接口实现多种数据库类型的灵活更换
  • 原文地址:https://www.cnblogs.com/little-w/p/3775471.html
Copyright © 2011-2022 走看看