描述
有 n 个男生和 n 个女生,第 i 的男生的能力值为 Ai,第 i 个女生的能力值为 Bi,第 i 个男生和第 j 个女生可以配对当且仅当 Ai ≤ Bj.
求有几种将他们配成 n 对男女的方案
输入
第一行一个正整数 n
第二行 n 个正整数,第 i 个正整数表示 Ai
第三行 n 个正整数,第 i 个正整数表示 Bi
有 30% 的数据满足 1 ≤ n ≤ 5
有100% 的数据满足 1 ≤ n ≤ 12,1 ≤ Ai,Bi ≤ 100
输出
输出有几种配对的方案
样例输入
3
1 2 3
3 3 1
样例输出
2
思路:
之前懂了状压dp,现在一看到数据量这么小,且每个人只用一次就想到状压dp了。我们可以用dp[k]表示所用女生的情况。k
表示女生状态 范围为
。女生j配对用1表示不配对用0表示。于是我们枚举男生,假设枚举到A[i],然后从大到小枚举女生配对的状态k,(从大到小是因为,每个女生只能配对一次,类似于01背包,保证后面状态只计算一次) 再看女生B[j]中哪个可以符合要求。具体条件为 (A[i] <=B[j] )且 k的第j位不是1,k的第j位为0 表示 B[j]可以和A[i]配对。那么转移方程为
; 最后所有女生都配对即k的每一位都为1时就是答案
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int dp[1<<13];
int main()
{
int A[15],B[15];
int n;
cin >> n;
for (int i = 0; i < n; ++i)
cin >> A[i];
for (int i = 0; i < n; ++i)
cin >> B[i];
dp[0] = 1;
for (int i = 0; i < n; ++i) {
for (int k = (1<<n)-1; k >= 0; --k) { //类似于01背包 保证每个状态是由前一个状态转移过来,而不会冲突
for (int j = 0; j < n; ++j) {
if (A[i] <= B[j]) {
if ((k & (1 << j) ) == 0)
dp[k|(1<<j)] += dp[k];
}
}
}
}
cout <<dp[(1<<n)-1] << endl;
return 0;
}