POJ 2411.Mondriaan's Dream 解题报告

题意:

      给出n*m (1≤n、m≤11)的方格棋盘,用1*2的长方形骨牌不重叠地覆盖这个棋盘,求覆盖满的方案数。

 

 

 


 

Solution:

               位运算+状态压缩+dp

               二进制数(####)代表填完一行后这一行的状态,填满的地方为1,未填的地方为0。

               显然在填第i行时,能改变的仅为第i-1行和第i行,因此要满足在填第i行时,第1~i-2行已经全部填满。

               DFS一行的状态,要是填完第i行时,第i-1行被填满。

               因此两行的状态(p1,p2)满足,~p1=p2;

              

               DFS出所有满足条件的状态对(P1,P2)

               ①第i行第k位为1,第i-1行第k位为0。(一块骨牌竖直放置)

                         dfs(k+1,last<<1,now<<1 | 1)

               ②第i行第k位为0,第i-1行第k位为1。 (第i行空出第k位)

                         dfs(k+1,last<<1 | 1,now<<1)

               ③骨牌横向放置。

                        bfs (k + 2, last << 2 | 3, now << 2 | 3)

               

               转移方程:F[i][sp1]=∑f[i-1][sp2]

 

代码:

 

#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
using namespace std;
int n, m, x;
LL f[12][1 << 12];
void dfs (int k, int last, int now) {
	if (k ==m )     f[x][now] += f[x - 1][last];
	if (k > m) return;
	dfs (k + 1, last << 1, now << 1 | 1);
	dfs (k + 1, last << 1 | 1, now << 1);
	dfs (k + 2, last << 2 | 3, now << 2 | 3);
}
int main() {
	while (~scanf ("%d %d", &n, &m) ) {
		if (n == 0) break;
		if (n > m)  swap (n, m);
		memset (f, 0, sizeof f);
		f[0][ (1 << m) - 1] = 1;
		for (x = 1; x <= n; x++)
			dfs (0, 0, 0);
		printf ("%lld\n", f[n][ (1 << m) - 1]);
	}
}

 

  

 

转载于:https://www.cnblogs.com/keam37/p/3834490.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值