AT4536 Matching(状压 dp)

Description

n n n 个男生和 n n n 女生,给定一个 n × n n \times n n×n 的 01 矩阵表示每对男女能否配对。求不同的配对方案数,每个人必须与一个异性配对。

1 ≤ n ≤ 21 1 \leq n \leq 21 1n21

Solution

数据范围告诉了我们状压 dp。

f i , m a s k f_{i,mask} fi,mask 为前 i i i 个男生配对的女生状态为 m a s k mask mask 的方案数,发现 i i i 其实是 m a s k mask mask 1 1 1 的个数,这个可以用双下划线函数 __builtin_popcount 求。所以枚举 m a s k mask mask,找一个女生与第 i i i 个男生配对即可。

时间复杂度为 O ( 2 n × n ) O(2 ^n \times n) O(2n×n)

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 21 + 5;
int n, a[N][N], f[1 << N], p = 1e9 + 7; 
int main() {
	int n; scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			scanf("%d", &a[i][j]);
	f[0] = 1;
	for (int mask = 0; mask < (1 << n); mask++) {
		int i = __builtin_popcount(mask);
		for (int j = 1; j <= n; j++) {
			if (mask & (1 << (j - 1)) && a[i][j])
				f[mask] = (f[mask] + f[mask ^ (1 << (j - 1))]) % p;
		}
	}
	printf("%d\n", f[(1 << n) - 1]);
	return 0;
} 
posted @ 2020-02-20 10:49  ylxmf2005  阅读(56)  评论(0)    收藏  举报