ZOJ 1425 Crossed Matchings(LCS变形)

题目大意:

  就是说给你两行数字,然后对于每一行的相同的数字进行连线,每次连接成功后,就算是1次成功,求最大的成功次数。当然,要成功的话,也是要满足一定的条件的:

  1.在连接的过程中,不能用两根线连接了4个相同数字。

  2.一个数字不能发出两条线。

解题思路:

  刚看到这个题,以为是图论的知识,感觉自己拿不下,,(有点像是什么二分图匹配吧,用两个颜色给相邻的顶点染色,求最多能有多少种这样的匹配,,逃)

其实呢,这个有点像LCS,,,我第一次也没看出来,看了题解后,才明白的。

  我们规定这样的状态: dp[i][j] 表示第一行前i个数字和第二行前j个数字的最大匹配数目.

            由LCS的状态转移方程知道:dp[i][j] = max( dp[i-1][j],dp[i][j-1]);

  那么我们由题目要求的定义知道,如果出现第1行的第i个字符和第二行的第j个字符不同的时候,也就是说a[i]!=b[j],那么,我们开始先定住a[i],从b[j]开始往前找,如果找到了a[i]==b[k]的位置,那就说明,在a[i]和b[k]之间就会有一条连线了。这时候,由于一个元素只能发出一条连接,我们查找结束。

  接下来,我们定住b[j]按照同样的方法来在a[l]中去找,找到第一个a[l]==b[j]的地方,我们就结束掉。分别记录这两次查找的过程中a[l]==b[j]和a[i]==b[k]的l和k的位置,更新dp[i][j]用,因为但凡有了这两次连线,对于dp[i][j]来说就会贡献2条线。。。如果我们在两次查找的过程中,有某一次或者两次的l和k的位置都没有出现的话,我们就说明dp[i][j]并没有得到更新。

代码:

 1 # include<cstdio>
 2 # include<iostream>
 3 # include<fstream>
 4 # include<algorithm>
 5 # include<functional>
 6 # include<cstring>
 7 # include<string>
 8 # include<cstdlib>
 9 # include<iomanip>
10 # include<numeric>
11 # include<cctype>
12 # include<cmath>
13 # include<ctime>
14 # include<queue>
15 # include<stack>
16 # include<list>
17 # include<set>
18 # include<map>
19 
20 using namespace std;
21 
22 const double PI=4.0*atan(1.0);
23 
24 typedef long long LL;
25 typedef unsigned long long ULL;
26 
27 # define inf 999999999
28 # define MAX 123
29 
30 int a[MAX];
31 int b[MAX];
32 int dp[MAX][MAX];
33 
34 int main(void)
35 {
36     int t;cin>>t;
37     while ( t-- )
38     {
39         int n,m;
40         cin>>n>>m;
41         for ( int i = 1;i <= n;i++ )
42             cin>>a[i];
43         for ( int i = 1;i <= m;i++ )
44             cin>>b[i];
45         int k,l;
46         for ( int i =1;i<= n;i++ )
47         {
48             for ( int j = 1;j <= m;j++ )
49             {
50                 dp[i][j] = max( dp[i-1][j],dp[i][j-1] );
51                 if ( a[i]!=b[j] )
52                 {
53                     for ( k = j-1;k >= 1;k-- )
54                     {
55                         if ( b[k]==a[i] )
56                             break;
57                     }
58                     for ( l = i-1;l >= 1;l-- )
59                     {
60                         if ( a[l]==b[j] )
61                             break;
62                     }
63 
64                     if ( l!=0&&k!=0 )
65                     {
66                         dp[i][j] = max(dp[i][j],dp[l-1][k-1]+2 );
67                     }
68                 }
69             }
70         }
71         cout<<dp[n][m]<<endl;
72 
73     }
74 
75 
76     return 0;
77 }
原文地址:https://www.cnblogs.com/wikioibai/p/4405581.html