点击这里查看原题
f[i][j][k]表示到第i行,摆放了j个国王且第i行摆法为k的方法数。
先预处理出所有摆法和摆法之间的转移关系,然后DP
/*
User:Small
Language:C++
Problem No.:1087
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=(1<<9)+5;
int n,m,c[M],num[M],tot;
bool ok[M][M];
ll ans,f[10][100][M];
void pre(){
for(int i=0;i<(1<<n);i++){
if((i&(i>>1))) continue;
c[++tot]=i;
for(int j=i;j;j>>=1) num[tot]+=(j&1);
}
for(int i=1;i<=tot;i++){
for(int j=1;j<=tot;j++){
if((c[i]&c[j])==0&&(c[i]&(c[j]>>1))==0&&(c[i]&(c[j]<<1))==0) ok[i][j]=1;
}
}
}
int main(){
freopen("data.in","r",stdin);//
scanf("%d%d",&n,&m);
pre();
for(int i=1;i<=tot;i++) f[1][num[i]][i]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=tot;j++){
for(int k=1;k<=tot;k++){
if(ok[k][j]){
for(int p=num[k];p+num[j]<=m;p++)
f[i][p+num[j]][j]+=f[i-1][p][k];
}
}
}
}
for(int i=1;i<=tot;i++) ans+=f[n][m][i];
printf("%lld\n",ans);
return 0;
}