车 题解
题目
在 n n n* n n n( n n n≤20)的方格棋盘上放置 n n n个车(可以攻击所在行、列),有些格子不能放,求使它们不能互相攻击的方案总数。
输入
第一行为棋盘的大小
n
n
n
第二行为障碍的数量
m
m
m
第三行到第
m
m
m+3为
m
m
m个障碍
输出
总数
样例
input
4
2
1 1
2 2
output
14
解题思路
状压DP
用二进制表示某种状态
在本题
0表示可放,1表示不可放
移位存储所有不可以放的位置
枚举所有状态
再枚举这个状态1在的位置
判断是否能放
能放就更新答案
代码
#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,x,y,f[2000100],p[30];
int main()
{
scanf("%lld%lld",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
p[x]+=1 << (y-1);
}
f[0]=1;
for (int i=0;i<(1<<n);i++)
{
int sum=0;
for (int j=i;j;j-=j & (-j)) //求出当前是第几行(因为一行只能放一个)
sum++;
for (int j=i;j;j-=j & (-j)) //枚举最后一个1,
if (!(p[sum] & (j & -j))) //判断是否能放
f[i]+=f[i & ~ (j & -j)]; //累加答案 (~是取反)
}
printf("%lld\n",f[(1<<n)-1]);
return 0;
}