// 题意:在一个n * n的棋盘上,放k个棋子使得每个棋子的周围八个区域都不得有其他棋子,问这样放置共有多少种
// 方法:状压+dp的水题 这几天都要被状压弄疯了
// dp[i][j][k] 代表第i行状态为j棋盘上总共放了k个棋子的方案数
// 然后由此行的状态j推出下一行不冲突的状态l就好了
// 巧妙利用 位运算和与运算来判断冲突 又快又方便
#include "iostream"
#include "string.h"
using namespace std;
int n, m;
long long dp[11][1<<10][105];
long long cnt[(1<<10)];
int calcu(int x)
{
int ans = 0;
for(int i = 0; i < 10; i++)
if(x & (1<<i)) ans++;
return ans;
}
int main()
{
for(int i = 0; i < (1<<10); i ++)
cnt[i] = calcu(i);
while(cin>>n>>m)
{
if(n%2 == 0 && m > (n * n / 4)) { //自作主张 稍微剪枝下 如果n是偶数 m不得超过(n*n)/2
cout<<0<<endl;
continue;
}
int maxn = (1<<n) - 1;
memset(dp, 0, sizeof dp);
for(int i = 0; i <= maxn; i++)
{
if(i & (i<<1)) continue;
if(cnt[i] <= m)
dp[1][i][cnt[i]] = 1;
}
for(int i = 1; i <= (n - 1); i++) //处理到第I行
{
for(int k = 0; k <= m; k++) //已经放了k个棋子
for(int j = 0; j <= maxn; j ++) //当前行的状态为j
{
if(j & (j<<1)) continue; //如果本行的状态不合法直接跳过
for(int l = 0; l <= maxn; l++) //枚举下一行的状态l
{
if(l & (l<<1)) continue; //如果状态l不合法直接跳过
if((l & j) || (l & (j<<1)) || (l & (j>>1))) continue; //如果两状态冲突
int t2 = cnt[l]; //计算出下一行放置棋子的数量
if(k + t2 < m) //如果当前所有放置棋子总和小于m
dp[i + 1][l][k + t2] += dp[i][j][k];
else if(k + t2 == m)
dp[i + 1][l][m] += dp[i][j][k];
}
}
}
long long ans = 0;
for(int j = 0; j <= maxn; j++) //把最后一行所有可行状态且总共放置m个棋子的所有方案数相加输出即可
ans += dp[n][j][m];
cout<<ans<<endl;
}
return 0;
}