SGC 131 Hardwood floor

Hardwood floor Time Limit:250MS    Memory Limit:4096KB    64bit IO Format:%I64d & %I64u
Appoint description:

Description

The banquet hall of Computer Scientists' Palace has a rectangular form of the size M x N (1<=M<=9, 1<=N<=9). It is necessary to lay hardwood floors in the hall. There are wood pieces of two forms:
1) rectangles (2x1)
2) corners (squares 2x2 without one 1x1 square)
You have to determine X - the number of ways to cover the banquet hall.
Remarks. The number of pieces is large enough. It is not allowed to leave empty places, or to cover any part of a surface twice, or to saw pieces.

Input

The first line contains natural number M. The second line contains a natural number N.

Output

First line should contain the number X, or 0 if there are no solutions.

Sample Input

2 3

Sample Output

5


题意:

       给出 n*m (1≤n、m≤9)的方格棋盘,用 1*2 的矩形的骨牌和 L 形的(2*2 的

去掉一个角)骨牌不重叠地覆盖,求覆盖满的方案数。

 

 


Solution:

             还是状态压缩,这次的情况比较多,要全部列出。

             b1,b2分别代表上下两行前列对下一列的影响

             s1,s2对应上下两行的状态

         情况

上列b1,b2要求

状态改变对下一列的影响

10

10

b1=0,

b2=0;

s1<<1,

s2<<1|1;

b1=0,

b2=0;

11

10

b1=0,

b2=0;

s1<<1,

s2<<1|1;

b1=1,

b2=0;

10

11

b1=0,

b2=0;

s1<<1,

s2<<1|1;

b1=0,

b2=1;

00

11

b2=0;

s1<<1|1-b1,

s2<<1|1;

b1=0,

b2=1;

01

11

b2=0;

s1<<1|1-b1,

s2<<1|1;

b1=1,

b2=1;

11

01

b1=0;

s1<<1,

s2<<1|b2;

b1=1,

b2=1;

00

00

s1<<1|1-b1,

s2<<1|b2;

b1=0,

b2=0;


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
#include <queue>
#include<algorithm>
#include <vector>
const double PI = acos(-1.0);
using namespace std;
long long dp[10][1 << 11], tep;//用tep记录上一行每个状态的dp值
int n, m;
void dfs(int k, int s1, int s2, int b1, int b2, int line)//s1为前一行状态, s2为当前行状态
{
	if(k >= m)
	{
		if(!b1 && !b2)
			dp[line][s2] += dp[line - 1][s1];
		return;
	}
	if(!b2)
	{
		if(!b1)
		{
			dfs(k + 1, s1 << 1, s2 << 1 | 1, 0, 0, line);
			dfs(k + 1, s1 << 1, s2 << 1 | 1, 1, 0, line);
			dfs(k + 1, s1 << 1, s2 << 1 | 1, 0, 1, line);	
		}
		 dfs(k + 1,(s1 << 1 | 1) - b1,s2 << 1 | 1, 0, 1, line);
		 dfs(k + 1,(s1 << 1 | 1) - b1,s2 << 1 | 1, 1, 1, line);
	}
	if(!b1)
		dfs(k + 1,s1 << 1,s2 << 1 | b2, 1 ,1 , line);
    dfs(k + 1,(s1 << 1 | 1)- b1, s2 << 1| b2, 0, 0, line);
}	
int main()
{
	int i, j, k;
	while(~scanf("%d%d", &n, &m))
	{
		memset(dp, 0, sizeof(dp));
		tep = 1;
		dp[0][(1 << m) - 1] = 1;
		for(i = 1; i <= n; ++ i)
			dfs(0, 0, 0, 0, 0, i);
		printf("%I64d\n", dp[n][(1 << m)- 1]);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值