题意:给定一个任意大小的矩形,用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; }