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 }

吐槽:

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

没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2711167.html