#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 12;
int n, m, cur;
LL d[2][1<<N];
void update(int a, int b){
/// 这里检查第一位是否为1是因为如果此处为空,之后的操作再也无法对该位进行填充,这样棋盘就会无法被填满。
if(b&(1<<m)) d[cur][b^(1<<m)] += d[cur^1][a];
}
int main(){
while(~scanf("%d%d", &n, &m)){
if(n < m) swap(n, m);
memset(d, 0, sizeof d);
cur = 0;
int tot = (1<<m) - 1;
d[0][tot] = 1;///in the begin, value is 1, nothing is placed.
///可以这样认为,上面的全部已经铺好,只剩下下面的,要看下面的铺满方式有多少种
///也可以这样认为,开始时棋盘为0*0的规格时,铺满棋盘有1种方式,就是什么都不放。
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
cur ^= 1;
memset(d[cur], 0, sizeof d[cur]);
for(int k = 0; k <= tot; k++){
update(k, k<<1);
if(i && !(k&(1<<m-1)))) update(k, (k<<1)^(1<<m)^1);
if(j && !(k&1)) update(k, (k<<1)^3);
}
}
printf("%I64d\n", d[cur][tot]);
}
return 0;
}
<pre name="code" class="cpp">#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define N 12
int n, m, cur;
LL dp[2][1<<N];
int update(int a, int b){
if(b&(1<<m)) {
dp[cur][b^(1<<m)] += dp[cur^1][a];
}
}
int main(){
while(~scanf("%d%d", &n, &m)){
if(n < m) swap(n, m);
int tot = (1<<m)-1;
memset(dp, 0, sizeof dp);
cur = 0;
dp[cur][tot] = 1;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
cur ^= 1;
memset(dp[cur], 0, sizeof dp[cur]);
for(int k = 0; k <= tot; k++){
update(k, k<<1);
if(i && !(k&(1<<(m-1)))) update(k, (k<<1)^(1<<m)^1);
if(j && !(k&1)) update(k, (k<<1)^3);
}
}
printf("%lld\n", dp[cur][tot]);
}
return 0;
}
/*
2 10
4 10
8 8
*/