ZOJ 1425 Crossed Matchings
题目描述:
题目链接:ZOJ 1425 Crossed Matchings
题目大意:
上下2组数据,找一个满足条件的最大匹配数。匹配条件是任意一个匹配的连线都要被至少另一个不一样的匹配交叉。每个点只能用一次。
解题思路:
使用dp[i][j]
表示一个行的前i个数与第二行的前j个数,共有dp[i][j]
个满足意义的描述。对于每一个新加入的数a[i]
,让其与b[1]-b[m]
依次匹配一遍。为了保证连线的交叉,作为枚举边界的a[i]
与b[j]
不能相等。
- 在没有出现满足提议的匹配点情况下状态转移方程为:
dp[i][j] = max(dp[i-1][j],dp[i][j-1]
; - 在出现满足提议的匹配点时状态转移方程为:
dp[i][j] = max(dp[i][j],dp[k1-1][k2-1] + 2)
。
复杂度分析:
时间复杂度 :
O(n∗m)
空间复杂度 :
O(n∗m)
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
const int maxn = 111;
int a[maxn], b[maxn];
int dp[maxn][maxn];
int main(){
int N;
cin >> N;
while(N--){
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= m; i++) cin >> b[i];
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++){
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
if(a[i] != b[j]){
int k1,k2;
for(k1 = j - 1; k1 > 0; k1--)
if(b[k1] == a[i])break;
for(k2 = i - 1; k2 > 0; k2--)
if(a[k2] == b[j])break;
if(k1 && k2)
dp[i][j] = max(dp[i][j],dp[k2-1][k1-1] + 2);
}
}
cout << dp[n][m] << endl;
}
}