POJ2411 状态压缩

Mondriaan‘s Dream
Time Limit: 3000MS        Memory Limit: 65536K
Total Submissions: 11208        Accepted: 6521
Description
Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his ‘toilet series‘ (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways. 



                                                                                              
Expert as he was in this material, he saw at a glance that he‘ll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won‘t turn into a nightmare!
Input

The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.
Output

For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.
Sample Input

1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
Sample Output

1
0
1
2
3
5
144
51205

0

经典状压,1*2的瓷片只有两种状态:1、横着贴    2、竖着贴。    横着贴表示为 1 1 ,竖着贴表示为1  ,那么贴完瓷片后整个墙被0和1两个数字覆盖,即每一行都是0和1,那么每一行可以用二进制数字表示,然后问题就成为上面一行的数字推出下面一行数字的问题。

怎么推呢,假设第i行第j个位置(用map[i][j]表示)为0,那么map[i+1][j]只能有一个状态即瓷片竖着贴,map[i+1][j]=1;

若map[i][j]=1,那么map[i+1][j]这个位置可以竖着贴,即map[i+1][j]=0是可以成立的。   那么map[i+1][j]可以横着贴吗?当然可以,不过要取决于map[i][j+1]位置的状态,若map[i][j+1]=0,那么map[i+1][j]只能竖着贴,若map[i][j+1]=1,那么map[i+1][j]=map[i+1][j+1]是可以成立的。

由这几个状态转化可以从上一行二进制数,把下一行二进制数推出。

代码:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <iostream>
 5 using namespace std;
 6
 7 int n, m;
 8 int used[12];
 9 __int64 dp[12][2048];
10
11
12 void dfs(int p,int q,int sum,int i)
13 {
14     if(i>=m)                                     //第i+1行每一列已求出
15     {
16         dp[p+1][sum]+=dp[p][q];
17         return;
18     }
19     if(used[i])                            //如果此处为0,那么下一行此处必为1
20     dfs(p,q,sum,i+1);
21     else{
22         int num1=1<<i;
23         int num2=1<<(i+1);
24         dfs(p,q,sum,i+1);                 //此处为1,下一行竖着贴
25         if(!used[i+1])
26             dfs(p,q,sum+num1+num2,i+2);    //此处为1,下一行横着贴
27     }
28 }
29
30 void flag(int p,int q)               //找出第i行二进制位为0的位置,并dfs
31 {
32     int x;
33     int sum=0, i;
34     memset(used,0,sizeof(used));
35     used[m]=0;
36     for(i=0;i<m;i++)
37     {
38         x=1<<i;
39         if((x&q)==0) {
40             used[i]=1;
41             sum+=x;
42         }
43     }
44     dfs(p,q,sum,0);
45 }
46 main()
47 {
48     while(scanf("%d %d",&n,&m)==2)
49     {
50         if(n==0&&m==0) break;
51         memset(dp,0,sizeof(dp));
52         if(n<m)
53         swap(n,m);
54         dp[0][(1<<m)-1]=1;
55         for(int i=0;i<n;i++)
56         {
57             for(int j=0;j<(1<<m);j++)
58             {
59                 if(!dp[i][j]) continue;               //当第i行二进制为j 该状态不成立的话跳过继续以另一个二进制循环,否则推出下一行二进制
60                 flag(i,j);
61             }
62         }
63         printf("%I64d\n",dp[n][(1<<m)-1]);    //易知,最后一行所有位置的二进制都为1
64     }
65 }

POJ2411 状态压缩,布布扣,bubuko.com

时间: 2024-08-05 19:37:34

POJ2411 状态压缩的相关文章

POJ2411——状态压缩+DFS——Mondriaan&#39;s Dream

Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and r

poj2411 状态压缩-铺地板题型

一种做法是先打出所有的状态,即满足上下配对的所有可能方案,然后再逐行进行枚举计数 dp[i][s]=sum{dp[i-1][t]},t是所有和s配对的状态 打状态时要注意如果i-1的j是0,那么i的j必定是1,i剩下的位置要必须一对对填入1,也可以用0填入,即枚举i行的横放砖块的起始位置k即可,如果i-1的k或k+1有一个不是1,那么显然不能放下 /* 对于每一行,用11表示一个横放的方块,用0表示竖放方块的第一格,1表示竖放方块的第二格 枚举i-1行的状态,推出i行的状态 如果i-1行的j位置

POJ2411 Mondriaan&#39;s Dream(状态压缩)

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

HihoCoder第九周 状态压缩 二 与POJ2411总结

在此我向各位博友求助,特别想知道除了HihoCoder上面的结果要对1e9+7取余之外,这两道题还有什么其他的问题,都是骨牌覆盖问题,都是状态压缩+dp,为什么我能过poj2411的程序过不了HihoCoder,还不是其他诸如TimeLimited,而是Wrong Answer,这个问题我想了很久,还是不知道是怎么回事,如果有神通广大的博友知道答案,希望你能告诉我.顺便说一下,HihoCoder给的那个hint只看懂了一部分递推的公式,其中满足的那个条件还是不懂. 两个题目的连接地址: http

Mondriaan的梦(状态压缩dp)

题目原题可以看POJ2411,大意是给出m*n的矩形,要用2*1的矩形将它铺满(不能讲一个矩形铺在另外一个上面),求方案数,并且只要不是完全相同的就算不同的方案,也就是对称算不同的方案. F[i][s]表示前i-1行已经填满,并且第i行的状态是s的方案数. F[i][s]=sum(F[i-1][s’]): s‘能转移到s.如何根据s来确定s'呢.这里用一个dfs实现,一位一位去填充s'.扫描s,如果该位是1,那么s’对应的这位必定是0,如果该位是0,那么要分情况讨论: 如果该位的后面一位也是0,

算法练习系列—hiho1048 状态压缩一(铺地砖)

题目地址:http://hihocoder.com/problemset/problem/1048 编程之美的课后题也有一个和整个题目一样的.(P269) 题目 这个题目的题意很容易理解,在一个N*M的格子里,我们现在有两种类型的砖块,1 * 2和 2 * 1,问一共有多少种方案,可以将整个N*M的空间都填满. 最简单的例子就是下面的了: 编程之美中题目: 某年夏天,位于希格玛大厦四层的微软亚洲研究院对办公楼的天井进行了一次大规模的装修.原来的地板铺有 N×M 块正方形瓷砖,这些瓷砖都已经破损老

状态压缩动态规划总结

状态压缩是一个很广的概念,在OI中也有很多的应用,当我们把他应用到动态规划中,可以用来精简状态,节约空间,也方便转移.最常见的就是用二进制来表是状态,利用各种位移运算,就可以实现\(O(1)\)的转移.状压DP适用于“窄棋盘”上的DP,否则状态太多无法存下. POJ1185 炮兵阵地 题意:给一个\(N \times M\)的地形盘,有平原和山坡,要求在平原上部署尽量多的炮(攻击范围2),使得不互相攻击. 数据范围:N <= 100:M <= 10,符合条件.如何表示状态?按行DP,一个二进制

[POJ 2411] Mondriaan&#39;s Dream 状态压缩DP

题意 给定一个 n * m 的矩形. 问有多少种多米诺骨牌覆盖. n, m <= 11 . 实现 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 #define LL long long 7 inline

状态压缩dp小结

最近一段时间算是学了一些状态压缩的题目,在这里做个小结吧 首先是炮兵布阵类题目,这类题目一开始给定一个矩形,要求在上面放置炮兵,如果在一格放了炮兵那么周围的某些格子就不能放炮兵,求最大能放置炮兵的数量 poj1185炮兵布阵 hdu2176 炮兵布阵修改版 poj3254 炮兵布阵弱化版 poj1565 方格取数 然后是状态集合类的题目,这类题目给定一个集合的元素,要求重排列以达到最大化收益,即从已知状态推出未知状态,通常需要处理出元素之间的两两对应关系 zoj3471 模板 poj2817 在