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;
}

posted @ 2025-10-23 10:20  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源