POJ 2411 Mondriaan's Dream

题目链接:http://poj.org/problem?id=2411

状态压缩Dynamic Programming. For each row, at ith position, 1 means that there is a block placed at this row and next row (vertically). otherwise, its 0. For the example in question, the state of

For the example in question, the state of first row is (00100001100) binary. The state of second row is (11010010000). and so on. The state of last row must be all 0 (has no influence in next row).

We use dp[i][j] to record the number of possible ways to place row i with state j. The final answer is dp[h][0]. In the initialization, all values in dp is 0 and dp[0][0]=1. if row i with state A matches next row j with state B, dp[j][B]+=dp[i][A].

代码如下:

  1 #include <iostream>
  2 #include <math.h>
  3 #include <stdio.h>
  4 #include <cstdio>
  5 #include <algorithm>
  6 #include <string.h>
  7 #include <string>
  8 #include <sstream>
  9 #include <cstring>
 10 #include <queue>
 11 #include <vector>
 12 #include <functional>
 13 #include <cmath>
 14 #include <set>
 15 #define SCF(a) scanf("%d", &a)
 16 #define IN(a) cin>>a
 17 #define FOR(i, a, b) for(int i=a;i<b;i++)
 18 #define Infinity 999999999
 19 typedef long long Int;
 20 using namespace std;
 21
 22 int h, w; //1 <= h, w <= 11
 23           //max states are 2^11 = 2048
 24 bool match[2048][2048];
 25 Int state[12][2048]; //i -> row, j -> state
 26 int states; //num of states for a row
 27
 28 bool check(int a, int b)
 29 {
 30     if (a&b)
 31         return false;
 32     int c = a | b;
 33     int zeroCon = 0;
 34     FOR(i, 0, w)
 35     {
 36         if (!(c & (1 << i)))
 37             zeroCon++;
 38         else
 39         {
 40             if (zeroCon % 2)
 41                 return false;
 42             else
 43                 zeroCon = 0;
 44         }
 45     }
 46     if (zeroCon % 2)
 47         return false;
 48     return true;
 49 }
 50
 51 int main()
 52 {
 53     FOR(i, 0, 12)
 54     {
 55         FOR(j, 0, 2048)
 56             state[i][j] = -1;
 57     }
 58
 59     while (scanf("%d %d", &h, &w) != EOF)
 60     {
 61         if (h == 0 && w == 0)
 62             break;
 63         if ((h*w) % 2)
 64         {
 65             printf("0\n");
 66             continue;
 67         }
 68
 69         if (h < w)
 70         {
 71             int temp = w;
 72             w = h;
 73             h = temp;
 74         }
 75
 76         states = (1 << w); // 0 - states-1
 77
 78         FOR(i, 0, states)
 79         {
 80             FOR(j, 0, states)
 81             {
 82                 match[i][j] = check(i, j);
 83             }
 84         }
 85
 86         FOR(i, 0, h + 1)
 87         {
 88             FOR(j, 0, states)
 89                 state[i][j] = 0;
 90         }
 91
 92         state[0][0] = 1;
 93
 94         FOR(i, 1, h + 1)
 95         {
 96             FOR(si, 0, states)
 97             {
 98                 FOR(sp, 0, states)
 99                 {
100                     if(match[sp][si]==true)
101                         state[i][si] += state[i - 1][sp];
102                 }
103             }
104         }
105
106         printf("%lld\n", state[h][0]);
107     }
108     return 0;
109 }

POJ 2411 Mondriaan's Dream

时间: 2024-12-23 20:51:09

POJ 2411 Mondriaan's Dream的相关文章

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看

POJ 2411 Mondriaan&#39;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

POJ 2411 Mondriaan&#39;s Dream ——状压DP 插头DP

[题目分析] 用1*2的牌铺满n*m的格子. 刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况. So Sad. 然后想到数据范围这么小,爆搜好了.于是把每一种状态对应的转移都搜了出来. 加了点优(gou)化(pi),然后poj上1244ms垫底. 大概的方法就是考虑每一层横着放的情况,剩下的必须竖起来的情况到下一层取反即可. 然后看了 <插头DP-从入门到跳楼> 这篇博客,怒抄插头DP 然后16ms了,自己慢慢YY了一下,写出了风(gou)流(pi)倜(bu)傥(tong)

POJ 2411 Mondriaan&#39;s Dream( 轮廓线dp )

最普通的轮廓线dp... 复杂度O(nm2min(n, m)) -------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; #define b(x) (1 << (x)) const in

POJ - 2411 Mondriaan&#39;s Dream (状态压缩)

题目大意:要在n * m的网格上面铺满1 * 2或者 2 * 1的砖块,问有多少种铺放的方式 解题思路:刚开始用了3进制表示每行的状态,0表示的是2 * 1的砖块的一部分,1表示的是1 * 2的砖块的上部分,2表示的是1 * 2的砖块的下部分,然后像poj-1185炮兵阵地 那题一样去解决就好了,结果发现状态太多了,会TLE,只得放弃了 后面参考了下别人的代码,可以将其转换成二进制表示形式的,0代表没该位置没被铺到,1代表该位置有被铺到 因为有1 * 2的这种影响两行的砖头存在,所以要判断两个状

poj 2411 Mondriaan&#39;s Dream 状压dp入门

题意: 求h*w的矩形被1*2的小矩形覆盖的方案数. 分析: 状压dp入门,<挑战程序设计竞赛>上讲的很好,好几天才看懂. 代码: #include <iostream> using namespace std; __int64 ans[16][16]; int n,m; __int64 dp[2][1<<16]; __int64 solve() { int i,j,used; memset(dp,0,sizeof(dp)); __int64 *crt=dp[0],*n

POJ 2411 Mondriaan&#39;s Dream (状压DP)

题意:给出一个n*m的棋盘,及一个小的矩形1*2,问用这个小的矩形将这个大的棋盘覆盖有多少种方法. 析:对第(i,j)位置,要么不放,要么竖着放,要么横着放,如果竖着放,我们记第 (i,j)位置为0,(i+1,j)为1,如果横着放,那么我们记 (i,j),(i,j+1)都为1,然后dp[i][s]表示 第 i 行状态为 s 时,有多少方法,那么我们就可以考虑与和匹配的状态,这个也很容易判断. 代码如下: #pragma comment(linker, "/STACK:1024000000,102

POJ 2411.Mondriaan&#39;s Dream 解题报告

题意: 给出n*m (1≤n.m≤11)的方格棋盘,用1*2的长方形骨牌不重叠地覆盖这个棋盘,求覆盖满的方案数. Solution:                位运算+状态压缩+dp                二进制数(####)代表填完一行后这一行的状态,填满的地方为1,未填的地方为0.                显然在填第i行时,能改变的仅为第i-1行和第i行,因此要满足在填第i行时,第1~i-2行已经全部填满.                DFS一行的状态,要是填完第i行时,