![]()
1 #include <iostream>
2 #include <cstdio>
3 #include <cmath>
4 #include <cstring>
5 using namespace std;
6
7 typedef long long LL;
8 const int MAXN=10;
9 const int MAXV=(1<<MAXN)+10;
10 const int MAXK=MAXN*MAXN;
11 int n,k;
12 LL dp[MAXN][MAXV][MAXK]; //第i行,状态为j,国王总个数为k的方案个数
13
14 int cnt[MAXV]; //每种状态有多少个1
15 inline void countOne() //统计
16 {
17 for (int i=0;i<(1<<n);i++) //枚举状态
18 {
19 int c=0;
20 for (int j=0;j<n;j++) //枚举位
21 {
22 if (i & (1<<j)) c++;
23 }
24 cnt[i]=c;
25 }
26 return;
27 }
28
29 int p[MAXV]; //满足同一行不矛盾的状态
30 int num=0; //状态个数
31 inline void checkLine() //同一行间互不攻击
32 {
33 for (int i=0;i<(1<<n);i++) //枚举状态
34 {
35 if (!((i & (i<<1)) | (i & (i>>1)))) p[++num]=i;
36 }
37 return;
38 }
39
40 int main()
41 {
42 scanf("%d%d",&n,&k);
43
44 countOne();
45 checkLine();
46
47 memset(dp,0,sizeof(dp));
48 for (int i=1;i<=num;i++)
49 {
50 int x=p[i];
51 dp[1][x][cnt[x]]=(LL)1;
52 }
53
54 for (int s=2;s<=n;s++) //枚举行
55 {
56 for (int j=1;j<=num;j++) //枚举本行状态
57 {
58 int y=p[j];
59 for (int i=1;i<=num;i++) //枚举上一行状态
60 {
61 int x=p[i];
62 if ((x & y) | (x & y<<1) | (x & y>>1)) continue; //上下两行间互相攻击,则跳过
63 for (int t=cnt[y];t<=k;t++) //枚举国王个数
64 {
65 dp[s][y][t]+=dp[s-1][x][t-cnt[y]];
66 }
67 }
68 }
69 }
70
71 LL ans=0;
72 for (int i=1;i<=num;i++)
73 {
74 int x=p[i];
75 ans+=dp[n][x][k];
76 }
77 printf("%lld\n",ans);
78
79 return 0;
80 }