POJ-2411 Mondriaan's Dream 状态压缩+DP
2012-03-23 09:53
471 查看
还记得杭电的“骨牌铺方格”吗,这题可以说是它的强化板了。但是思路是一样的,就是通过得到前面的解来递推后面的结果。
由于是一个较大的平面,较之杭电那题在行数和列数上都有了较多的组合情况,因此状态压缩有了用武之地。
这题的一个难点就是如何用0,1来表示摆放的规律,参看别人的想法后,找到的这种方法虽然时间开销相对大了点,但是思路非常好理解。
对于每一个格子,只有0,1两种状态,0代表没有放置,1代表放置。对于每一行的状态,1的含义会因为上一行的对应项而不同,如果与之对应的上一行的列为0的话,那么这个1代表这里放置了一个竖直的块,如果上一列是1的话那么两行都必须是横着放置的。
定义了这些后,就是写代码了,本来在judge函数中想通过位运算来解决,但是采用这样的0,1定义对位运算不利,这也是为什么时间开销比较大的原因,在judge时采用了传统的解压方式......逐个判定。
1. 初始化
2. dfs出第一行的状态,注意第一行的1必须要相邻,而且必须是偶数个,能够想清楚吗?
3. DP更新
代码如下:
由于是一个较大的平面,较之杭电那题在行数和列数上都有了较多的组合情况,因此状态压缩有了用武之地。
这题的一个难点就是如何用0,1来表示摆放的规律,参看别人的想法后,找到的这种方法虽然时间开销相对大了点,但是思路非常好理解。
对于每一个格子,只有0,1两种状态,0代表没有放置,1代表放置。对于每一行的状态,1的含义会因为上一行的对应项而不同,如果与之对应的上一行的列为0的话,那么这个1代表这里放置了一个竖直的块,如果上一列是1的话那么两行都必须是横着放置的。
2411 | Accepted | 328K | 1844MS | C++ | 2143B |
1. 初始化
2. dfs出第一行的状态,注意第一行的1必须要相邻,而且必须是偶数个,能够想清楚吗?
3. DP更新
代码如下:
#include <cstdlib> #include <cstring> #include <cstdio> #include <iostream> using namespace std; int H, W, cnt; unsigned int MaxN; long long dp[15][1050]; void print(int x, int L) { if (x != 0) { print(x >> 1, --L); printf("%d", x % 2); } else { while (L--) printf("0"); } } inline int lowbit(int x) { return x & -x; } void dfs(int p, int num, int total) { if (p == W){ if (!(total & 1)){ dp[1][num] = 1; } return; } else{ if (total & 1) dfs(p+1, num<<1|1, total+1); else{ dfs(p+1, num<<1, total); dfs(p+1, num<<1|1, total+1); } } } int judge(int x, int y) { for (int i = 0; i < W; ++i) { if (x>>i & 1) {// 第i位为奇数 if (y>>i & 1) { if (i == W-1) return 0; else if (!(x>>(i+1)&1 && y>>(i+1)&1)){ return 0; } else ++i; } } else if (!(y>>i & 1)){ return 0; } } return 1; } void DP() { for (int i = 2; i <= H; ++i) { // 针对行的一个遍历 for (int j = 0; j <= MaxN; ++j) { // 针对状态的一个遍历 for (int k = 0; k <= MaxN; ++k) { // 针对状态的一个遍历 if (judge(k, j)) { dp[i][j] += dp[i-1][k]; } } } } } void init() { memset(dp, 0, sizeof (dp)); if (!(H & 1) && !(W & 1)) { // 将状态变小 if (H < W) { H = H + W; W = H - W; H = H - W; } } else if (!(H & 1)) { H = H + W; W = H - W; H = H - W; } MaxN = (1<<W)-1; // 所有的可能性 dfs(0, 0, 0); } int main() { while (scanf("%d %d", &H, &W), H|W) { if (W & 1 && H & 1) { puts("0"); continue; } init(); DP(); cout << dp[H][MaxN] << endl; } return 0; }
相关文章推荐
- HDU 1400 (POJ 2411 ZOJ 1100)Mondriaan's Dream(DP + 状态压缩)
- poj 2411 Mondriaan's Dream(压缩状态dp)
- poj 2411 Mondriaan's Dream(状态压缩dp)
- POJ_2411_Mondriaan's Dream_状态压缩dp
- POJ 2411 Mondriaan's Dream [经典状态压缩dp]
- poj 2411 Mondriaan's Dream 状态压缩DP 打表
- poj 2411 Mondriaan's Dream 状态压缩DP
- POJ 2411 Mondriaan's Dream(状态压缩DP)
- poj 2411 Mondriaan's Dream 状态压缩dp
- POJ-2411 Mondriaan's Dream 状态压缩DP
- poj 2411 Mondriaan's Dream_状态压缩dp
- poj 2411 Mondriaan's Dream(状态压缩dP)
- POJ 2411 Mondriaan's Dream(压缩DP)
- POJ 2411 && HDU 1400 Mondriaan's Dream(状态压缩DP)
- poj 2411 Mondriaan's Dream(状态压缩+dp)
- POJ 2411 Mondriaan's Dream 状态压缩dp
- poj 2411/hdu 1400 Mondriaan's Dream 状态压缩dp
- poj 2411 Mondriaan's Dream 状态压缩dp
- Chapter06-Mondriaan's Dream(POJ 2411)(状态压缩DP)
- Mondriaan's Dream - POJ 2411(状态压缩)