首页 > 代码库 > POJ 2411 Mondriaan's Dream(状压DP)

POJ 2411 Mondriaan's Dream(状压DP)

http://poj.org/problem?id=2411

求一个n*m矩阵用1*2方块去填满的情况有几种

思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况

然后就一层层往后递推即可

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int n, m, g[15555][2], gn;
long long dp[2][2111];

void dfs(int len, int now, int pre) {
    if (len > m) return;
    if (len == m) {
	g[gn][0] = pre;
	g[gn++][1] = now;
	return;
    }
    dfs(len + 2, (now<<2)|3, (pre<<2)|3);
    dfs(len + 1, (now<<1)|1, pre<<1);
    dfs(len + 1, now<<1, (pre<<1)|1);
}

int main() {
    while (~scanf("%d%d", &n, &m) && n || m) {
	if (n < m) swap(n, m);
	gn = 0;
	dfs(0, 0, 0);
	printf("%d\n", gn);
	memset(dp, 0, sizeof(dp));
	dp[0][(1<<m) - 1] = 1;
	for (int i = 1; i <= n; i++) {
	    int now = i%2;
	    int pre = !now;
	    memset(dp[now], 0, sizeof(dp[now]));
	    for (int j = 0; j < gn; j++) {
		dp[now][g[j][1]] += dp[pre][g[j][0]];
	    }
	}
	printf("%lld\n", dp[n % 2][(1<<m) - 1]);
    }
    return 0;
}