Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
题解
和玉米田(轻击有惊喜)的解法一样。预处理一行所有合法情况。由于是四周的八个格子都不能有国王,在判断时多一个左移、右移,然后dp扫一遍
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=1e9;
const int maxn=(1<<9)+10;
typedef long long ll;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,k;
int is[maxn];
ll f[10][maxn][90];
int main(){
n=read();k=read();
for(int i=0;i<(1<<n);i++){
is[i]=((i&(i<<1))==0)&&((i&(i<<1))==0);
if(is[i]){
int num=__builtin_popcount(i);
if(num>k)continue;
f[1][i][num]=1;
}
}
for(int i=2;i<=n;i++) for(int j=0;j<(1<<n);j++)
if(is[j]){
int num1=__builtin_popcount(j);
for(int p=0;p<(1<<n);p++) if(((p&j)==0)&&((p&(j<<1))==0)&&((p&(j>>1))==0))
for(int q=0;q<=k-num1;q++) f[i][j][q+num1]+=f[i-1][p][q];
}
ll ans=0;
for(int i=1;i<=n;i++) for(int j=1;j<(1<<n);j++)
if(is[j])ans+=f[i][j][k];
printf("%lld
",ans);
return 0;
}