首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

交错匹配

完全自己写出来的DP,好开心QvQ

原题:

 有两行自然数,UP[1..N],DOWN[1..M],如果UP[I]=DOWN[J]=K,那么上行的第I个位置的数就可以跟下行的第J个位置的数连一条线,称为一条K匹配,但是同一个位置的数最多只能连一条线。另外,每个K匹配都必须且至多跟一个L匹配相交且K≠L  。现在要求一个最大的匹配数。
例如:以下两行数的最大匹配数为8

0<N、M<=200

 

最开始考虑怎么转移,从左往右转移,从右往左转移,两行分别设一个f然后取最小值……

然后怎么搞都不行啊

认真思考两天颓了一中午看动漫后,突然灵光一闪就莫名奇妙get到做法了

既然是双进程,就开个二维数组,完全排除两条线之间乱七八糟的干扰

然后在每个决策点(i,j)从1到i-1找一个点p,在从1到j-1找一个点q,如果i,j,p,q能形成一个交错匹配,f[i][j]=max(f[i][j],f[p-1][q-1]+1);

还有一个问题就是每次到一个决策点(i,j)的时候这个决策点的初始值应该是(1到i-1,1到j-1)的最优质,刚开始的时候写的是在开始的时候f[i][j]=max(f[i-1][j-1],max(f[i-1][j],f[j][i-1])),然后WA了,不知道为什么酱紫不能把前面所有的最优状态转移过去

cydiater大神的思路似乎和我不一样,而且我做的时候找交错匹配的时候是直接枚举找,用个东西存一下复杂度会更低,然而数据太水我枚举也很快过了一。一

差点就看题解了,看题解的话就没有锻炼机会了

如果DP的时候没有思路或会遇到很多乱七八糟的东西干扰状态的话,可以开多维将干扰状态的东西也设成一维状态

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int n,m,a[210],b[210];
 8 int f[210][210];
 9 int main(){//freopen("ddd.in","r",stdin);
10     memset(f,0,sizeof(f));
11     cin>>n>>m;
12     for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
13     for(int i=1;i<=m;i++)  scanf("%d",&b[i]);
14     for(int i=1;i<=n;i++)
15         for(int j=1;j<=m;j++){
16             for(int p=1;p<=i;p++)
17                 for(int q=1;q<=j;q++)
18                     f[i][j]=max(f[i][j],f[p][q]);//不知道为什么不能直接取f[i-1][j-1],f[i-1][j],f[i][j-1]的最大值
19             if(a[i]!=b[j]){
20                 for(int p=1;p<i;p++)if(a[p]==b[j])
21                     for(int q=1;q<j;q++)if(b[q]==a[i]){
22                         f[i][j]=max(f[i][j],f[p-1][q-1]+1);
23                         //cout<<i<<" "<<j<<" "<<p<<" "<<q<<endl;
24                     }
25             }
26         }
27     cout<<f[n][m]*2<<endl;
28     return 0;
29 }
View Code

 

posted on 2016-10-20 16:46  cdcq_old  阅读(369)  评论(0编辑  收藏  举报