这种类型的题是每行只能取一个位置的,并且保证不能相互冲突的棋盘问题。
因为每一行只取一个,所以枚举状态的时候只需要枚举当前的状态
#include<iostream>
using namespace std;
int n,m;
int a[30][30];
int f[21][1<<20];
int ar[21];
int ss[21];
void dfs(int l,int k,int s)
{
if(k==l){
if(l==1)
f[1][s]=1;
ss[++m]=s;
return ;
}
for(int i=1;i<=n;i++){
if(!(s&(1<<(i-1))))
dfs(l,k+1,s+(1<<(i-1)));
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
ar[i]=0;
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
ar[i]=(ar[i]<<1)|a[i][j];
}
}
for(int i=1;i<=n;i++){
m=0;
dfs(i,0,0);//枚举状态
for(int j=1;j<=m;j++){
int s=ss[j]&ar[i];
for(int k=1;k<=n;k++){
if(((1<<(k-1))&s)==0)
f[i+1][s+(1<<(k-1))]+=f[i][s];
}
}
}
cout<<f[n][(1<<n)-1]<<endl;
return 0;
}