车
Description
在n*n(n≤20)的方格棋盘上放置n个车(可以攻击所在行、列),有些格子不能放,求使它们不能互相攻击的方案总数。
Input
第一行为棋盘的大小n
第二行为障碍的数量m
第三行到第m+3为m个障碍
Output
总数
Sample Input
4
2
1 1
2 2
Sample Output
14
思路:
用
a
i
a_i
ai 表示第i行的状态,1为障碍,0为无障碍。那它怎么转移呢?
a[i]+=1 << (y - 1);
注意:它是在边数人边输出的,x,y表示障碍的位置。
接着我们设f[i]表示选了i个车的最多方案总数。那是不是根据加法原理,我们将当前状态前面的所有状态加一个总,那是不是就是f[i]的最大值
for(ll i=1,c,j ; i<(1 << n) ; i++)
{
for(c=0,j=i ; j ; j-=(j & -j),c++);
for(j=i&~a[c]; j; j-=(j&-j)) f[i]+=f[i^(j&-j)];
}
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#define ll long long
#define fre(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout);
using namespace std;
const ll MAX=2147483647;
const ll N=1 << 20;
ll n, m, x, y, a[N], f[N]={1};
int main()
{
scanf("%lld%lld",&n, &m);
for(ll i=1; i<=m; i++) scanf("%lld%lld", &x, &y), a[x]+=1 << (y - 1);
for(ll i=1, c, j; i<(1 << n) ; i++)
{
for(c=0, j=i ; j ; j-=(j & -j),c++);
for(j=i&~a[c]; j; j-=(j&-j)) f[i]+=f[i^(j&-j)];
}
printf("%lld",f[(1 << n) - 1]);
return 0;
}