题意:
n*m的矩形用2*1的矩形铺满一共可以有多少种方法?
分析:
思路来自评论区大神的思路:
用2进制的01表示不放还是放 第i行只和i-1行有关 枚举i-1行的每个状态,推出由此状态能达到的i行状态 如果i-1行的出发状态某处未放,必然要在i行放一个竖的方块,所以我对上一行状态按位取反之后的状态就是放置了竖方块的状态。 然后用搜索扫一道在i行放横着的方块的所有可能,并且把这些状态累加上i-1的出发状态的方法数,如果该方法数为0,直接continue。 举个例子 2 4 1111 1111 状态可以由 1100 0000 0110 0011 1111 0000 0000 0000 0000 0000 这五种i-1的状态达到,故2 4 的答案为5
通俗易懂,学习了。
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m;
ll dp[12][1<<12];
ll tmp;
void solve(int i,int s,int pos){
if(pos==m){
dp[i][s]+=tmp;
return ;
}
solve(i,s,pos+1);
if(pos<=m-2&&!(s&(1<<pos))&&!(s&(1<<pos+1)))
solve(i,s|(1<<pos)|(1<<pos+1),pos+2);
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
tmp=1;
memset(dp,0,sizeof dp);
solve(1,0,0);
for(int i=2;i<=n;i++){
for(int j=0;j<(1<<m);j++){
if(dp[i-1][j]) tmp=dp[i-1][j];
else continue;
solve(i,(~j)&((1<<m)-1),0);
}
}
printf("%lld\n",dp[n][(1<<m)-1]);
}
return 0;
}