説明

n * n(n≤20)の正方形のチェスボードにn台の車を配置します(行と列を攻撃できます)。一部の正方形は配置できません。互いに攻撃できないプランの総数を見つけます。

入力

1行目のチェス盤のサイズn2行目
の障害物の数mm
+3までの3行目はm個の障害物です

出力

合計

サンプル入力

4
2
1 1
2 2

サンプル出力

14

思路:
a i a_i Ai番目の行のステータスを示し、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;
} 

おすすめ

転載: blog.csdn.net/bigwinner888/article/details/108094339