#include<bits/stdc++.h>
using namespace std;
int n,k;//棋盘行数 国王总数
int cnt;//同一行的合法状态个数
int s[1<<12];//同一行的合法状态集
int num[1<<12];//每个合法状态包含的国王数
long long f[12][144][1<<12];
//f[i,j,a]表示前i行放了j个国王 第i行第a个状态时的方案数
int main(){
cin>>n>>k;//输入行数 国王总数
for(int i=0;i<(1<<n);i++)//枚举一行的所有状态
if(!(i&i>>1)){//如果不存在相邻的1
s[cnt++] = i;//保存一行的合法状态
for(int j=0;j<n;j++)
num[i]+=(i>>j&1);//统计每个合法状态包含的国王数
}
f[0][0][0] = 1;//不放国王也是一种方案
for(int i=1;i<=n+1;i++)//枚举行
for(int j=0;j<=k;j++)//枚举国王数
for(int a=0;a<cnt;a++)//枚举第i行的合法状态
for(int b=0;b<cnt;b++){//枚举第i-1行的合法状态
int c = num[s[a]];//第i行第a个状态的国王数
//可以继续放国王 不存在同列的1 不存在斜对角的1
//c为每个状态需要的国王数 所以j>=c
// s[b]&s[a]判断是否在同一列上
// (s[b] & (s[a]>>1))判断是否在左上角
// (s[b] & (s[a]<<1))判断是否在右上角
if((j>=c) && !(s[b]&s[a]) && !(s[b] & (s[a]<<1)) && !(s[b] & (s[a]>>1)))
f[i][j][a] += f[i-1][j-c][b];
}
cout<<f[n+1][k][0]<<endl;//第n+1行什么都不放 相当于只在1~n行放国王
return 0;
}
小国王(状态压缩dp)
最新推荐文章于 2023-04-15 18:48:45 发布