AT_dp_o Matching题解
题目描述
有 N 名男性和 N 名女性。男性编号为 1,2,…,N,女性也编号为 1,2,…,N。
对于每一对 i,j(1≤i,j≤N),男性 i 和女性 j 的匹配情况由整数 ai,j 给出。如果 ai,j=1,则男性 i 和女性 j 匹配良好;如果 ai,j=0,则匹配不好。
太郎君想要将所有匹配良好的男女分别配对,组成 N 对。每个男性和每个女性都必须恰好属于一对。
请问有多少种组成 N 对的方法?请输出对 109+7 取模的结果。
输入格式
输入通过标准输入给出,格式如下:
N
a1,1 a1,2 … a1,N
a2,1 a2,2 … a2,N
⋮
aN,1 aN,2 … aN,N
输出格式
输出组成 N 对的方法数,对 109+7 取模。
显示翻译
题意翻译
输入输出样例
输入 #1复制
3 0 1 1 1 0 1 1 1 1
输出 #1复制
3
输入 #2复制
4 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0
输出 #2复制
1
输入 #3复制
1 0
输出 #3复制
0
输入 #4复制
21 0 0 0 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 0 0 1 1 1 0 1 1 0 0 0 1 1 1 1 0 1 1 0 0 1 0 0 1 1 0 0 0 1 1 0 1 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 0 1 1 1 0 0 0 1 1 1 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 1 1 1 0 1 1 0 0 0 1 0 0 1 1 1 1 0 1 1 0 1 1 1 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 0 1 1 0 1 0 1 1 1 1 1 1 1 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0 1 0 0 0 1 1 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 0 1 0 0 1 0 0 1 1 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 1 1 1 1 1 0 1 0 1 1 0 0 0 0 0
输出 #4复制
102515160
说明/提示
限制条件
- 所有输入均为整数。
- 1≤N≤21
- ai,j 仅为 0 或 1。
样例解释 1
组成配对的方法有以下 3 种。用 (i,j) 表示男性 i 和女性 j 的配对。
- (1,2), (2,1), (3,3)
- (1,2), (2,3), (3,1)
- (1,3), (2,1), (3,2)
样例解释 2
组成配对的方法有以下 1 种。
- (1,2), (2,4), (3,1), (4,3)
样例解释 4
不要忘记输出对 109+7 取模的结果。
由 ChatGPT 4.1 翻译
思路
状压DP。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,a[22][22],f[2500006],rm[22],cc=0,c[22],op=0,mod=1e9+7;
int main(){
cin>>n;
rm[0]=1;
for(int i=1;i<=n;i++){
rm[i]=rm[i-1]*2;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
f[0]=1;
for(int i=1;i<=rm[n]-1;i++){
cc=i;
op=0;
for(int j=0;j<=n-1;j++){
if(cc%2==1){
c[j+1]=1;
op++;
}
else{
c[j+1]=0;
}
cc/=2;
}
for(int j=1;j<=n;j++){
if(c[j]==1&&a[op][j]==1){
f[i]+=f[i-rm[j-1]];
}
}
f[i]%=mod;
}
cout<<f[rm[n]-1]<<endl;
return 0;
}

浙公网安备 33010602011771号