Description
【问题描述】
Wcyz为了迎接百年校庆,美化校园,请了校友笨笨将n座雕塑,准备安置在校园内,整个校园可以抽象成一个nn的大网格,每个11网格最多只能安置一座雕塑,但是某些1*1的网格上恰好是一个食堂或湖泊,这些网格是不能安置雕塑的,每个雕塑的造型相同,这样同一种安置方案中交换排列都算一种。任意雕塑在同一行或同一列是不合法的方案。
学校想知道有多少种安置方案,笨笨想从中选择最好的一种方案,笨笨想请你告诉他方
案种数。
Input
【输入格式】
第一行,两个整数n,m(n<=20,m<=10),用空格隔开,n表示n*n的大网格,m表示不能安置雕塑的位置
第二行至m+1行,每行两个数x,y,用空格分开,表示坐标(x,y)的1*1 的网格上不能安置雕塑。
Output
【输出格式】
一个数,方案种数(方案种数<=2^63-1)
Sample Input
6 7
1 1
2 1
2 2
3 3
3 4
4 3
4 4
Sample Output
184
Data Constraint
Hint
n<=20,m<=10
.
.
.
.
.
.
分析
.
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,x[15],y[15];
long long ans,jc[25],tj;
bool han[25],lie[25];
void dfs(int i,int cnt,int sum)
{
if (cnt==sum)
{
tj++;
return;
}
if (i>m) return;
if (han[x[i]]==false&&lie[y[i]]==false)
{
han[x[i]]=lie[y[i]]=true;
dfs(i+1,cnt+1,sum);
han[x[i]]=lie[y[i]]=false;
}
dfs(i+1,cnt,sum);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
scanf("%d%d",&x[i],&y[i]);
jc[0]=1;
for (int i=1;i<=n;i++)
jc[i]=i*jc[i-1];
ans=jc[n];
for (int i=1;i<=m;i++)
{
tj=0;
dfs(1,0,i);
if (tj==0) break;
if (i%2==1) ans-=tj*jc[n-i]; else ans+=tj*jc[n-i];
}
printf("%lld",ans);
return 0;
}