题目描述
在 N × N N×N N×N 的棋盘里面放 K K K 个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 8 8 8 个格子。
输入格式
只有一行,包含两个数 N , K N,K N,K。
输出格式
所得的方案数。
Input
3 2
Output
16
数据范围与提示
1 ≤ N ≤ 9 , 0 ≤ K ≤ N × N 1≤N≤9,0≤K≤N×N 1≤N≤9,0≤K≤N×N
思路
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k] 表示在棋盘的前 i i i 行,放置了 j j j 颗棋子,并且第 i i i 行棋子的状态为 k k k 时,放置方法的数量。
f [ i ] [ j ] [ k ] = ∑ k & k ′ = 0 & & p [ k ∣ k ′ ] = 0 f [ i − 1 ] [ j − c [ k ] ] [ k ′ ] f[~i~][~j~][~k~]=\sum_{k\&k'=0 ~\&\&~p[k|k']=0 } f[~i-1~][~j-c[k]~][~k'~] f[ i ][ j ][ k ]=k&k′=0 && p[k∣k′]=0∑f[ i−1 ][ j−c[k] ][ k′ ]
p
[
k
&
k
′
]
=
0
p[k\&k']=0
p[k&k′]=0 代表
k
&
k
′
k\&k'
k&k′ 二进制下没有连续的
1
1
1。
c
[
k
]
c[k]
c[k] 代表
k
k
k 二进制下有多少个
1
1
1。
答案为 ∑ 0 ≤ x < ( 1 < < n ) f [ n ] [ k ] [ x ] \sum_{0\le x <(1<<n)} f[n][k][x] ∑0≤x<(1<<n)f[n][k][x].
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=12,M=(1<<12);
int n,k,f[N][N*N][M],p[M],c[M],ans;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=0;i<(1<<n);i++){
int flag=0,cnt=0;
for(int j=0;j<n;j++){
if(i>>j&1) flag|=cnt,cnt=1,c[i]++;
else cnt=0;
}
p[i]=flag;
}
f[0][0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=k;j++)
for(int k=0;k<(1<<n);k++)
for(int s=0;s<(1<<n);s++)
if((k&s)==0&&p[s|k]==0&&j-c[k]>=0)
f[i][j][k]+=f[i-1][j-c[k]][s];
for(int i=0;i<(1<<n);i++)
ans+=f[n][k][i];
cout<<ans<<"\n";
}