题意:给定一个矩阵,只能放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;
}
本文探讨了如何计算在给定矩阵中使用1*2的木块进行完全覆盖的不同方法数量,通过分析相邻两行的状态合集是否满足覆盖条件来解决此问题。
1692

被折叠的 条评论
为什么被折叠?



