poj2411--Mondriaan's Dream(状压dp+dfs)

Mondriaan‘s Dream

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 12315   Accepted: 7189

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

1*2的长方形木块,问组成h*w的大长方形的种数。

从第 i行放一个小木块后,可能会对下一行造成影响,但最多只会影响到下一层。

dp[i][j]代表第当1到i-1行铺满后,第i行为状态j的种数。状态j为每一行的二进制压缩1代表存在了木块,0代表不存在。在第i行遍历所有的j,对每一个状态进行dfs,找到可以填满的一种情况,得到下一行的状态。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define LL __int64
LL dp[15][2100] ;
int h , w ;
void dfs(int low_i,int low_j,int k1,int k2,int i)
{
    if( i == w )
    {
        dp[low_i+1][k2] += dp[low_i][low_j] ;
        return ;
    }
    if( (k1 & (1<<i)) )
    {
        dfs(low_i,low_j,k1,k2,i+1) ;
        return ;
    }
    dfs(low_i,low_j,k1|(1<<i),k2|(1<<i),i+1) ;
    if( i+1 < w && (k1&(1<<(i+1))) == 0 )
        dfs(low_i,low_j,(k1|(1<<i))|( 1<<(i+1) ),k2,i+2) ;
    return ;
}
int main()
{
    int m , i , j ;
    while( scanf("%d %d", &h, &w) != EOF )
    {
        if( h == 0 && w == 0 ) break ;
        memset(dp,0,sizeof(dp)) ;
        dp[1][0] = 1 ;
        m = 1 << w ;
        for(i = 1 ; i <= h ; i++)
        {
            for(j = 0 ; j < m ; j++)
            {
                dfs(i,j,j,0,0);
            }
        }
        printf("%I64d\n", dp[h+1][0]) ;
    }
    return 0;
}

poj2411--Mondriaan's Dream(状压dp+dfs)

时间: 2024-10-11 17:29:59

poj2411--Mondriaan's Dream(状压dp+dfs)的相关文章

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 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 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入门

题意: 求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 状压DP

题目链接:http://poj.org/problem?id=2411 把每一行当作一个二进制状态. 1表示是一个竖着的1*2的方格. 0表示其他状态. 那么显然当i-1的状态k能转移到i的j: 1.j 和 k 的按位与为0.(有1必须要0,0也可以有1) 2.j 和 k 按位或每一段0都有偶数个.(表示横着的长方形) 那么就可以预处理一下合格的点. 然后状压DP. 代码如下: #include<cstdio> using namespace std; int n,m; long long f

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

Language: Default Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12405   Accepted: 7239 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in

[状压DP][DFS]JZOJ 2679 跨时代

Description 钟逆时针而绕,恶物狰狞的倾巢,我谦卑安静地于城堡下的晚祷,压抑远古流窜的蛮荒暗号,而管风琴键高傲的说,那只是在徒劳.我的乐器在环绕,时代无法淘汰我霸气的皇朝. 你无法预言,因为我越险,翅越艳:没有句点,跨时代蔓延,翼朝天. 月下浮雕,魔鬼的浅笑,狼迎风嚎,蝠翔似黑潮,用孤独去调尊严的色调.我跨越过世代,如兽般的姿态,琴声唤起沉睡的血脉.不需要被崇拜,如兽般的悲哀,只为永恒的乐曲存在,醒过来. 去年万众瞩目的<跨时代>专辑发行之后,周杰伦又开始了他的世界巡回演唱会<

【题解】P3959 宝藏 - 状压dp / dfs剪枝

P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m  条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多. 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上,小明还需要考虑如何开凿