关闭

poj2411Mondriaan's Dream【覆盖类状压dp】

标签: poj状态压缩dp
309人阅读 评论(0) 收藏 举报
分类:

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

今天晚上状态超级不好啊==本文参考:点击打开链接

题意:用1x2的方块密铺nxm的矩形,问方法数,一看题就想到了hdu2946骨牌铺方格,只不过那个题是只有两行,其实只有两行就足以找出规律:

1.假设已知Fibo(n),如果将第n+1块板竖着插入排头,会发现并没有多出组合,Fibo(n+1)=Fibo(n),插入其他位置的情况下,
如果第n+1个位置是竖板,等同于前面的情况。
2.只有在n和n+1的位置是横板,才能多出组合,多的组合数量为Fibo(n-1);
3.推出 Fibo(n+1)=Fibo(n)+Fibo(n-1);即为Fibo(n)=Fibo(n-1)+Fibo(n-2);

同理我们考虑不止两行的情况,假设枚举到了第i行,前i-2行已经密铺了,将每行的骨牌有无压缩至一个十进制的二进制对应位,这个so easy吧,ss,s分别表示上行i-1状态和本行i状态,就像其他的dp题一样,状态不是直接找的对应的来转化的,而是判断两个状态是否可以转化再转化,这个过程就是下面的solve。重点是ok()这个判断函数:

1.第i行的第j列为1,第i-1行的第j列为1,这样的话,说明第i行的第j列一定不是竖放而是横放否则会与第i-1行的第j列冲突
  所以马上紧接着判断第i行第j+1列,如果是1,那么满足横放的规则,同时也要第i-1行第j+1列也要为1,否则的话这个格子没办法填充,
  成立后向左移动两格
  不满足上述条件的,就是两个不兼容或者不合法的状态
2.第i行第j列为1,第i-1行第j列为0,那么说明第i行第j列应该竖放并填充第i-1行第j列,成立后向左移动一格
3.第i行第j列为0,说明不放方块,那么第i-1行第j列必须为1,否则没法填充这个格子。若第i-1行第j列也为0,不兼容不合法
  (至于第i行第j列这个格子空着干什么,其实就是留出来给第i+1行竖放的时候插进来的)
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 15
#define MAX (1<<11)+10
long long dp[N][MAX];
long long ans[N][N];
int n,m;
bool init(int s)
{
    for(int i=0;i<m;)
    {
        if(s&(1<<i))
        {
            if(i==m-1) return false;
            if(s&(1<<(i+1)))i+=2;
            else return false;
        }
        else i++;
    }
    return true;
}
bool ok(int s,int ss)
{
    for(int i=0;i<m;)
    {
        if(s&(1<<i))
        {
            if(ss&(1<<i))
            {
                if(i==m-1||!(s&(1<<(i+1)))||!(ss&(1<<(i+1))))return false;
                i+=2;
            }
            else i++;
        }
        else
        {
            if(ss&(1<<i))i++;
            else return false;
        }
    }
    return true;
}
void solve()
{
    if(n<m) swap(m,n);
    memset(dp,0,sizeof(dp));
    int maxn=(1<<m)-1;
    for(int i=0;i<=maxn;i++)
        if(init(i))
            dp[1][i]=1;
    for(int i=2;i<=n;i++)
        for(int s=0;s<=maxn;s++)
            for(int ss=0;ss<=maxn;ss++)
                if(ok(s,ss))
                    dp[i][s]+=dp[i-1][ss];
    printf("%I64d\n",dp[n][maxn]);
}
int main()
{
    //freopen("cin.txt","r",stdin);
    while(~scanf("%d%d",&n,&m))
    {
        if(m==0&&n==0) break;
        if(m*n%2)
        {
            printf("0\n");
            continue;
        }
        solve();
    }
    return 0;
}


0
0
查看评论

poj 2411 骨牌覆盖问题 状压dp

题目:点击打开链接 题意:用1*2 的矩形通过组合拼成大矩形,求拼成指定的大矩形有几种拼法 分析: 这题的关键在于什么状态是合法的,可以这样想,用1表示有骨牌覆盖,用0表示空着。在覆盖第i行的时候,那么如果覆盖的状态是合法的,覆盖完后第i-1行必须没有空格了(全是1111),所以...
  • loveyou11111111
  • loveyou11111111
  • 2016-02-27 00:04
  • 517

POJ2411——Mondriaan's Dream(轮廓线dp入门)

Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 15207 Accepted: 8771 ...
  • say_c_box
  • say_c_box
  • 2016-08-03 20:12
  • 436

poj2411Mondriaan's Dream(状态压缩dp)

Mondriaan's DreamTime Limit:3000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u SubmitS...
  • zjw6463
  • zjw6463
  • 2016-03-01 14:19
  • 140

【POJ2411】Mondriaan's Dream-状态压缩DP(插头DP?)

【POJ2411】Mondriaan's Dream-状态压缩DP(插头DP?)
  • Maxwei_wzj
  • Maxwei_wzj
  • 2017-03-20 17:46
  • 259

Mondriaan's Dream 瓷砖覆盖地板 编程之美

Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his ‘toilet series’...
  • qq_36183935
  • qq_36183935
  • 2017-04-27 19:27
  • 260

poj2411Mondriaan's Dream

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11810   Accepted: 6...
  • tjqACM
  • tjqACM
  • 2014-09-06 19:47
  • 241

poj2411Mondriaan's Dream题解

题目大意:给出h*w(1≤h、w≤11)的方格棋盘,用1*2 的长方形骨牌不重叠地覆盖这个 棋盘,求覆盖满的方案数。 输入文件包含多组数据。 每组数据有一行,两个正整数h,w。 输入结束标志为h=w=0. 对每组数据,输出一行一个正整数,即方案总数。解析详见代码:#include<c...
  • qq_27138357
  • qq_27138357
  • 2015-08-01 17:43
  • 467

对状压dp的一点理解

博主是初学者,一下紧代表个人观点,若有错误欢迎指出。 状压dp       此dp可以理解为最暴力的dp,因为他需要遍历每个状态,所以将会出现2^n的情况数量,所以明显的标志就是数据不能太多(好像是 for(s=1;s<(1<<15);s++) {...
  • benTuTuT
  • benTuTuT
  • 2017-04-12 21:51
  • 846

状压DP问题

状态压缩·一题目传送:#1044 : 状态压缩·一AC代码:#include <map> #include <set> #include <list> #include <cmath> #include <deque> ...
  • u014355480
  • u014355480
  • 2015-08-17 15:00
  • 878

状压DP 入门题

一:方格取数 问题描述: Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数。 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。 Input 包括多个测试实例,每个测试实例包括一个整数n 和n*...
  • sinat_34336698
  • sinat_34336698
  • 2016-08-06 16:33
  • 1614
    碎碎念
    周小姐,你还想毕业找不到工作吗????
    个人资料
    • 访问:280056次
    • 积分:8809
    • 等级:
    • 排名:第2603名
    • 原创:608篇
    • 转载:25篇
    • 译文:0篇
    • 评论:38条
    友情链接