車
説明
n * n(n≤20)の正方形のチェスボードにn台の車を配置します(行と列を攻撃できます)。一部の正方形は配置できません。互いに攻撃できないプランの総数を見つけます。
入力
1行目のチェス盤のサイズn2行目
の障害物の数mm
+3までの3行目はm個の障害物です
出力
合計
サンプル入力
4
2
1 1
2 2
サンプル出力
14
思路:
用 a i a_i A私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;
}