题目链接

题目

题目描述

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!

输入描述

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≤111\leq h,w\leq 111≤h,w≤11.

输出描述

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.

示例1

输入

1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0

输出

1
0
1
2
3
5
144
51205

题解

知识点:状压dp。

一道经典的状压dp,状态设置十分巧妙。考虑一行一行摆,因为要摆满且有两种块,单纯用 \(01\) 表示横着摆竖着摆会出问题,竖着的会影响下一行,横着的要连着放,非常麻烦。考虑设 \(dp[i][st]\) 表示考虑第 \(i\) 行, 且状态是 \(st\) ,其中 \(1\) 代表这格会延长至下一行,\(0\) 代表这格不会延长至下一行。这样,如果上一行状态是 \(st1\) ,这一行状态是 \(st2\) ,\(st1 | st2\) 中 \(1\) 表示这一行哪些格子被竖着的块占据了,两行的 \(1\) 都对应一个竖块,剩下的 \(0\) 则是横的,于是统计连续出现的 \(0\) 是否为奇数,如果是则状态组合 \(st1 | st2\) 不可能发生。

先预处理出状态组合 \(st1|st2\) 是否可能发生,共 \(2^m\) 种可能,记录在 \(vis\) 数组。

接下来枚举行,本层状态和上层状态,满足 j & k || !vis[j | k] == 1 则不合法,否则有转移方程:

\[dp[i][j] = \sum dp[i-1][k]
\]

时间复杂度 \(O(n \cdot 4^m)\)

空间复杂度 \(O(n \cdot 2^m)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; ll dp[12][1 << 11];///第 i 行,状态 j,0表示横着放中的一格或者上上层竖着放下来的(即没有往下延伸),1表示竖着放(往下延伸了)
bool vis[1 << 11]; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
while (cin >> n >> m, n || m) {
for (int i = 0;i < (1 << m);i++) {///这里的状态不一样,1 表示单独存在的,0 表示是连续两个的
vis[i] = 1;
bool ok = 1;
for (int j = 1;j <= m;j++) {
if (((i >> (j - 1)) & 1)) vis[i] &= ok, ok = 1;
else ok ^= 1;
}
vis[i] &= ok;///最后没有1的残留状态转移
}
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1;i <= n;i++) {
for (int j = 0;j < (1 << m);j++) {///本层
for (int k = 0;k < (1 << m);k++) {///上层
if (j & k || !vis[j | k]) continue;
///第一个判断1是否重叠,因为上面1,下面不能放1
///第二个判断,把上面戳下来的一起当作1表示独立一格,记录连在一起的0的个数是否是偶数
dp[i][j] += dp[i - 1][k];
}
}
}
cout << dp[n][0] << '\n';///最终一定是全0,不会往下戳的情况
}
return 0;
}

NC51189 Mondriaan's Dream的更多相关文章

  1. POJ 题目2411 Mondriaan's Dream(状压DP)

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13519   Accepted: 787 ...

  2. HDU 1400 (POJ 2411 ZOJ 1100)Mondriaan's Dream(DP + 状态压缩)

    Mondriaan's Dream Problem Description Squares and rectangles fascinated the famous Dutch painter Pie ...

  3. POJ2411 Mondriaan's Dream(状态压缩)

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 15295   Accepted: 882 ...

  4. POJ 2411 Mondriaan's Dream -- 状压DP

    题目:Mondriaan's Dream 链接:http://poj.org/problem?id=2411 题意:用 1*2 的瓷砖去填 n*m 的地板,问有多少种填法. 思路: 很久很久以前便做过 ...

  5. POJ2411 铺地砖 Mondriaan's Dream

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 15962   Accepted: 923 ...

  6. [poj P2411] Mondriaan's Dream

    [poj P2411] Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 18023   A ...

  7. POJ 2411 Mondriaan's Dream 插头dp

    题目链接: http://poj.org/problem?id=2411 Mondriaan's Dream Time Limit: 3000MSMemory Limit: 65536K 问题描述 S ...

  8. 【POJ2411】Mondriaan's Dream(轮廓线DP)

    [POJ2411]Mondriaan's Dream(轮廓线DP) 题面 Vjudge 题解 这题我会大力状压!!! 时间复杂度大概是\(O(2^{2n}n^2)\),设\(f[i][S]\)表示当前 ...

  9. poj2411 Mondriaan's Dream【状压DP】

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20822   Accepted: 117 ...

  10. POJ - 2411 Mondriaan's Dream(轮廓线dp)

    Mondriaan's Dream Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One nig ...

随机推荐

  1. Git | git branch 分支操作

    假设我们已经有了稳定的代码,现在我想整一些花活.比较安全的一个方式是,在新的分支上整活. 新建 vga 分支:git branch vga,然后切换到 vga 分支:git switch vga,或者 ...

  2. Hystrix 实现服务熔断与降级

    本文为博主原创,未经允许不得转载: 目录: 1. 服务雪崩,服务熔断,服务降级概念 2. Hystrix 概念 3. Hystrix 使用及默认配置 4. @HystrixCommond 注解使用 5 ...

  3. 01-UPF介绍

    Mainstream Low Power techniques clock gating - 低功耗的设计风格,4bit以上可以通过综合工具增加ICG APR的时候可以更换器件VT Advanced ...

  4. 基于AHB_BUS的eFlash控制器设计-软硬件系统设计

    eFlash软硬件系统设计 软硬件划分 划分好软硬件之后,IP暴露给软件的寄存器和时序如何? 文档体系:详细介绍eflash控制器的设计文档 RTL代码编写:详细介绍eflash控制器的RTL代码 1 ...

  5. P5707 【深基2.例12】上学迟到

    1.题目介绍 2.题解 这里只有两个稍微注意的点 2.1 s % v != 0(向上取整) 这里的话,若是结果不为整数,我们必须向上取整,必须保证空余时间永远大于所需时间! 2.2 ceil向上取整函 ...

  6. 【MicroPython】用 c 添加接口 -- 框架介绍

    [来源]https://www.eemaker.com/micropython-c-kuangjia.html

  7. 【lvgl-micropython】官方源码之ports/unix 编译报错

    lv_micropython/ports/unix make 报错 编译环境如下 这是缺少SDL2库导致的 sudo apt-get install libsdl2-2.0 sudo apt-get ...

  8. [转帖]Linux_Redhat8——常用命令:ls、ll、vim、ps、top、grep、tail

    Linux_Redhat8-常用命令: ls.ll.vim.ps.top.grep 一.ls(list):查看目录下的文件 ls:仅罗列出当前文件名或目录名. ll:罗列出当前文件或目录的详细信息,包 ...

  9. [转帖]Jmeter性能测试:高并发分布式性能测试

    一.为什么要进行分布式性能测试 当进行高并发性能测试的时候,受限于Jmeter工具本身和电脑硬件的原因,无法满足我们对大并发性能测试的要求.基于这种场景下,我们就需要采用分布式的方式来实现我们高并发的 ...

  10. [转帖]linux删除文本文件空白行

    linux删除文本文件空白行https://www.zhihu.com/people/chen-kai-84-54-75 sed命令 在Linux中,可以使用sed命令批量删除文本中的空白行.以下是一 ...