POJ 2411(状态压缩DP)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2411(状态压缩DP)相关的知识,希望对你有一定的参考价值。
题意:一个矩阵,只能放1*2的木块,问将这个矩阵完全覆盖的不同放法有多少种。
如果是横着的就定义11,如果竖着的定义为竖着的01,这样按行dp只需要考虑两件事儿,当前行&上一行,是不是全为1,不是说明竖着有空(不可能出现竖着的00),另一个要检查当前行里有没有横放的,但为奇数的1。
状态表示 dp[state][i]第i行状态为state时候的方案数
转移方程 dp[state][i] += dp[state‘][i-1] state‘为i-1行的,不与i行状态state冲突的状态
边界条件 第一行 符合条件的状态记为1 即dp[state][0] = 1;
#include <algorithm> #include <cstdio> #include <cstring> #define Max 1000001 #define MAXN 11 #define MOD 100000000 #define rin freopen("in.txt","r",stdin) #define rout freopen("1.out","w",stdout) #define Del(a,b) memset(a,b,sizeof(a)) #define INF 0x1f1f1f1f using namespace std; typedef long long LL; const int MAXNUM = (1 << MAXN); int n, m; int a[MAXN][MAXN]; LL dp[MAXNUM][MAXN]; int kexing[MAXNUM]; inline bool check(int in) { int bit = 0; while (in > 0) { if ((in & 1) == 1) bit++; else { if ((bit & 1) == 1) return false; bit = 0; } in >>= 1; } if ((bit & 1) == 1) return false; return true; } inline bool check2(int x1, int x2) { if ((x1 | x2) != ((1 << n) - 1)) return false; return kexing[x1 & x2]; } int main() { //rin; for (int s = 0; s < MAXNUM; s++) { if (check(s)) kexing[s] = 1; } while (scanf("%d%d", &m, &n) != EOF) { if (n == 0 && m == 0) break; Del(dp, 0); int full = 1 << n; for (int s = 0; s < full; s++) { if (kexing[s]) dp[s][0] = 1; } for (int i = 1; i < m; i++) { for (int s = 0; s < full; s++) { for (int s1 = 0; s1 < full; s1++) { if (!check2(s1, s)) continue; dp[s][i] += dp[s1][i - 1]; } } } printf("%lld\n", dp[full-1][m-1]); } return 0; }
以上是关于POJ 2411(状态压缩DP)的主要内容,如果未能解决你的问题,请参考以下文章
(hiho1048)POJ2411Mondriaan's Dream(DP+状态压缩 or 轮廓DP)
[POJ 2411] Mondriaan's Dream 状态压缩DP
POJ 2411题解Mondriaan's Dream 状压DP