題意:給定一個矩陣,只能放1*2的木塊,問將這個矩陣完全覆蓋的不同放法有多少種。
分析:橫著放為11,豎著放為豎著的01,所以判斷相鄰兩行是否被完全覆蓋:只需判斷兩行狀態合集(j | k)是否是滿的, 兩種狀態是否有沖突(j & k)。
第一行直接預處理就行。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
__int64 dp[12][1 << 11]; //橫著放為11,豎著放為0
// 1
int buff[1 << 11];
int n,m;
__int64 ans;
bool judge(int b) {
bool flag = 1;
while(b) {
if(b & 1) {
if((b >> 1) & 1) b = b >> 2;
else {
flag = 0;
b = b >> 1;
}
} else b = b >> 1;
if(flag == 0) return 0;
}
return flag;
}
void getbuff() {
int total = 1 << 11;
for(int i=0; i<total; i++) {
if(judge(i)) {
buff[i] = 1;
}
}
}
void solve() {
int total = 1 << m;
for(int i=1; i<n; i++) { //最後一行一定全是1
for(int j=0; j<total; j++) {
for(int k=0; k<total; k++) {
if((j | k) == total-1 && buff[(j & k)]) {
dp[i][j] += dp[i-1][k];
}
}
}
}
ans = dp[n-1][total-1];
}
int main() {
getbuff();
while(scanf("%d%d",&n,&m) ) {
if(n == 0 && m == 0 ) break;
if(n == 1) {
if(m % 2 == 0) printf("1\n");
else printf("0\n");
continue;
}
int total = 1 << m;
memset(dp,0,sizeof(dp));
for(int i=0; i<total; i++) {
if(buff[i]) dp[0][i] = 1;
}
ans = 0;
solve();
printf("%I64d\n",ans);
}
return 0;
}