[状态压缩DP] PKU 2411 Mondriaan's Dream
参考http://wenku.baidu.com/view/e262a86f1eb91a37f1115c26.html
状态设计:0表示横放,1表示竖放,可以预处理出所有合法状态,f[i, s] 表示到达第 i 层的状态(类似俄罗斯方块,前 i 层合并之后剩余的状态)。
状态转移:f[i, s] = sum{f[i-1, s']},s' 为和 s 符合的状态 j 与 s 的异或值。
# include <cstdio> # include <cstring> # define N 11 + 1 typedef long long int LL; int m, n; LL f[N][1<<N]; bool check(int x) { int tmp = 0; for (int i = 0; i < n; ++i) { if ((x>>i)&0x1) continue; else { while (i<n && (((~x)>>i)&0x1)) { ++i; ++tmp; } if (tmp & 0x1) return false; else tmp = 0; } } //printf("%04X\n", x); return true; } LL dp(int i, int s) { //printf(" : %d\n", i); LL &ans = f[i][s]; if (ans != -1) return ans; ans = 0; for (int j = 0; j < (1<<n); ++j) { if ((j^s)==j-s && check(j)) ans += dp(i-1, j^s); } return ans; } void solve(void) { memset(f[0], 0, sizeof(LL)*(1<<n)); f[0][0] = 1; for (int i = 1; i <= m; ++i) memset(f[i], -1, sizeof(LL)*(1<<n)); LL ans = dp(m, 0); // 0 ~ n-1 printf("%lld\n", ans); } int main() { while (scanf("%d%d", &m, &n), m||n) solve(); return 0; }