poj 2411 状态压缩(矩形铺砖)

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


你可能感兴趣的:(poj 2411 状态压缩(矩形铺砖))