题意:给定一个任意大小的矩形,用1*2的小矩形砖完全铺满,问有多少种铺放方法。
思路:状态压缩。每行用二进制数字表示一种铺法。注意宏的写法!
输入:
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
输出:
1
0
1
2
3
5
144
51205
#include <stdio.h>
#include <string.h>
#define swap(x,y,i) {i=x;x=y;y=i;}//这段代码原封不动,所以大括号必须加上
#define N (1<<12)
__int64 dp[11][N];
int n,m,M;
int testfirstline(int x){
int temp = 1;
while(temp<M){
if(temp&x){//如果当前测试位为1,那么它左边的位也必为1,否则此种铺法不合理
if((temp<<1>=M) || ((temp<<1)&x)==0)
return 0;
temp <<= 1;
}
temp <<= 1;
}
return 1;
}
int test(int x,int y){
int temp = 1;
while(temp<M){
if((temp&y)==0){//如果当前位为0,则其正上方必不为零
if((temp&x)==0)
return 0;
}else{
if((temp&x)){//如果当前位和正上方均为1,那么这两位左边的位也必为1
if(((temp<<1)<M) && ((temp<<1)&x) && ((temp<<1)&y))
temp <<= 1;
else
return 0;
}
}
temp <<= 1;
}
return 1;
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d %d",&n,&m)&&n&&m){
int i,j,k;
memset(dp,0,sizeof(dp));
if(n<m)
swap(n,m,i);
M = 1<<m;
for(i = 0;i<M;i++)
if(testfirstline(i))//第一行的判断与其他行不同,故单独判断
dp[0][i] = 1;
for(i = 1;i<n;i++)
for(j = 0;j<M;j++)
for(k = 0;k<M;k++)
if(test(k,j))
dp[i][j] += dp[i-1][k];
printf("%I64d\n",dp[n-1][M-1]);
}
return 0;
}