题目链接
#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 */