Acwing 291. 蒙德里安的梦想

2023-11-16

 

 

题目分析
摆放方块的时候,先放横着的,再放竖着的。总方案数等于只放横着的小方块的合法方案数

如何判断,当前方案数是否合法? 所有剩余位置能否填充满竖着的小方块。可以按列来看,每一列内部所有连续的空着的小方块需要是偶数个。

这是一道动态规划的题目,并且是一道 状态压缩的dp:用一个N位的二进制数,每一位表示一个物品,0/1表示不同的状态。因此可以用0→2^N−1(N二进制对应的十进制数)0→2^N−1(N二进制对应的十进制数)中的所有数来枚举全部的状态。

状态表示
状态表示:f[i][j]表示已经将前 i -1 列摆好,且从第i−1列,伸出到第 i列的状态是 j 的所有方案。其中j是一个二进制数,用来表示哪一行的小方块是横着放的,其位数和棋盘的行数一致。


状态转移
既然第 i 列固定了,我们需要看 第i-2 列是怎么转移到到第 i-1列的(看最后转移过来的状态)。假设此时对应的状态是k(第i-2列到第i-1列伸出来的二进制数,比如00100),k也是一个二进制数,1表示哪几行小方块是横着伸出来的,0表示哪几行不是横着伸出来的。

它对应的方案数是 f[i−1,k],即前i-2列都已摆完,且从第i-2列伸到第i-1列的状态为 k 的所有方案数。

这个k需要满足什么条件呢?

首先==k不能和 j在同一行==:因为从i-1列到第i列是横着摆放的12的方块,那么i-2列到i-1列就不能是横着摆放的,否则就是1 3的方块了!这与题意矛盾。所以 k和j不能位于同一行。

既然不能同一行伸出来,那么对应的代码为(k & j ) ==0 ,表示两个数相与,如果有1位相同结果就不是0, (k & j ) ==0表示 k和j没有1位相同, 即没有1行有冲突。

既然从第i-1列到第i列横着摆的,和第i-2列到第i-1列横着摆的都确定了,那么第i-1列 空着的格子就确定了,这些空着的格子将来用作竖着放。如果 某一列有这些空着的位置,==那么该列所有连续的空着的位置长度必须是偶数==。

总共m列,我们假设列下标从0开始,即第0列,第1列……,第m-1列。根据状态表示f[i ] [j] 的定义,我们答案是什么呢? 请读者返回定义处思考一下。答案是f[m][0], 意思是 前m-1列全部摆好,且从第m-1列到m列状态是0(意即从第m-1列到第m列没有伸出来的)的所有方案,即整个棋盘全部摆好的方案。

时间复杂度
dp的时间复杂度 =状态表示× 状态转移

状态表示 f[i][j] 第一维i可取11,第二维j(二进制数)可取2^11 ,所以状态表示 11×2^11
状态转移 也是2^11
所以总的时间复杂度
11×2^11×2^11≈4×10^7 可以过

题解转载自:https://www.acwing.com/solution/content/28088/
 

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 12, M = 1 << N;

bool st[M];
long long f[N][M];
int n, m;

int main()
{
    while (cin >> n >> m, n || m)
    {
        memset(f, 0, sizeof(f));
        
        for (int i = 0; i < 1 << n; ++ i)
        {
            st[i] = true;
            int cnt = 0;
            for (int j = 0; j < n; ++ j)
            {
                if (i >> j & 1)
                {
                    if (cnt & 1) st[i] = false;
                    cnt = 0;
                }
                else cnt ++;
            }
            if(cnt & 1) st[i] = false;
        }
        
        f[0][0] = 1;
        for (int i = 1; i <= m; ++ i)
            for (int j = 0; j < 1 << n; ++ j)
                for (int k = 0; k < 1 << n; ++ k)
                    if ((j & k) == 0 && st[j | k])
                        f[i][j] += f[i - 1][k];
                        
        cout << f[m][0] << endl;
    }
    
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Acwing 291. 蒙德里安的梦想 的相关文章

随机推荐

  • 技术人员的赚钱之道-2:做个现代的“六化”程序员

    六化 像是一面黑夜中的灯塔 在黑暗指明方向 六化 可是现代程序员具备的能力水平 六化 也可以是程序员轻创业的方式 什么是六化 专业化 数字化 自动化 虚拟化 云化 智能化 1 专业化 专业化是程序员的基础 懂得编程或某个专业领域的技术 2
  • Ubuntu20.04 LTS 安装GCC11.2教程,包教包会!

    GCC 11 2 安装 其他版本 如9 5 12 1等都可以用同样方法编译安装 但是依赖包不一样 需要到gcc官网下载对应的依赖包和源码包 前置条件 首先把Ubuntu提供的各种构建工具都给他装上 sudo apt install buil
  • 好分数阅卷3.0_揭秘!自考阅卷的批改套路!

    距离2019年4月自考仅剩 13 天 每当考试之后有小伙伴就有这样的感受 自己感觉这次可以 及格没问题 但是最后却是差了几分 也有人说 我都抄到了标准答案 为什么是56分 56分啊 难道自考真的有所谓的过关率 阅卷老师真的有刻意在压低分数
  • C++顺序表的构建(用数组存储数据)

    这是最简单的顺序表 顺序表中的元素都存储在数组T data中 const int defaultSize 100 template
  • 3399的-mipi适应多个lcd屏显示-后续2-linux内核中的修改

    一 前提 1 rk3399核心板 2 linux4 4 19 源码 3 多个MIPI显示屏的启动序列以及显示时序 重要 4 rk3399MIPI通道0 5 接上一个uboot中的修改配置 二 内核驱动的修改 0 dts就不再给出了 请参考u
  • 【PyQT5教程】-01入门PyQT5

    PyQT介绍 1 Qt 1 1 介绍 Qt 读作 cute 是一个跨平台的C 应用程序开发框架 最初由挪威公司Trolltech 现在是Qt公司的一部分 开发 Qt提供了一系列工具和类库 用于开发图形界面应用程序 命令行工具和服务器端应用程
  • k8s v1.16设置Job ttlSecondsAfterFinished不生效

    目录 Completed的job默认不会清理 配置自动清理job ttl机制自动清理完成的job ttl controller 开启 TTLAfterFinished kube apiserver开启TTLAfterFinished kub
  • 【C++】异常

    文章目录 C语言错误处理 异常的概念 异常的使用 异常的抛出匹配原则 异常的栈展开匹配原则 异常安全 异常的重新抛出 异常规范 异常体系 C 标准库的异常体系 异常的优缺点 C语言错误处理 在C语言中 因为没有异常这个机制 所以出现错误时一
  • AD20/Altium designer——如何给元器件添加3D模型

    3D模型网站 https www 3dcontentcentral cn Browse aspx eventSource mnuFindContent 1 进入3D模型下载网站 搜索并找到自己需要的模型下载 2 AD中添加3D模型 1 打开
  • 利用Laplacian变换进行图像模糊检测

    转自 https www cnblogs com arkenstone p 7900978 html 利用Laplacian变换进行图像模糊检测 检测图片是否模糊有很多方法 这篇文章review了36种 比如FFT和variation of
  • 小白都能轻松掌握,python最稳定的图片识别库ddddocr

    本文目录 前言 测试 对比Pytesseract 使用ddddocr 简介 实战 成果 前言 在爬虫过程中 大多我们都会碰到验证码识别 它是常用的一种反爬手段 包括 滑块验证码 图片验证码 算术验证码 点击验证码 所讲的图片验证码是较简单的
  • 要跳过磁盘检查,请在5秒内按任意键如何解决

    要跳过磁盘检查 请在5秒内按任意键如何解决 电脑每次开机都出 需要做张pe启动盘 进pe系统修复c盘
  • mysql之联合查询(union)15

    1 联合查询 union 本篇是我们讲述DQL数据查询语言最后的进阶 不难 主要需要注意它的特点 即易错点即可 进阶9 联合查询 union 联合 合并 将多条查询语句的结果合并成一个结果 语法 查询语句1 union 查询语句2 unio
  • OnnxRuntime 性能调优

    OnnxRuntime 性能调优 文档的一些笔记 性能调优小工具 ONNX GO Live Tool 这玩意儿有俩docker容器来实现支持 一个优化容器和一起模型转换容器 暂时具体不清楚原理 还没来得及看 后面试试 什么执行单元 Exec
  • 01背包问题(动态规划)

    问题描述 给定n种物品和一个背包 物品i的重量是wi 其价值为vi 背包容量是c 问应如何选择装入背包中的中的物品 使得装入物品的总价值最大 问题分析 我们用m i j 表示i n的物品放入容量为j的背包里可以取得的最大价值 cw表示当前背
  • spring boot 项目打jar包,并转换exe文件

    今天学习股票小知识 自己做了一个 简便的小程序 可以查询基金方面的数据 不想每次都打开软件在开启项目 所以制作了一个exe的启动程序 当然啦 遇到了一些坑的地方 记录一下 方便后期需要的时候不用再重新踩一遍 前提 spring boot项目
  • Vue脚手架搭建及创建Vue项目

    一 什么是Vue脚手架 Vue脚手架是Vue官方提供的标准化开发工具 开发平台 它提供命令行和UI界面 方便创建vue工程 配置第三方依赖 编辑vue工程 二 Vue脚手架搭建过程 1 安装Node js 官网 Node js 中文网 2
  • Qt自学之路(二)-信号及槽机制

    1 信号与槽机制介绍 Qt提供信号与槽机制 用于类间通信 类似于观察者模式 信号相当于主题 槽相当于观察者 但是不同于观察者模式的地方为 1 槽可以连接多个信号 2 信号可以跨线程通知槽 队列连接 2 信号 1 信号通过emit命令进行发送
  • 计算机网络安全设计毕业设计,计算机网络安全及防护毕业设计论文01

    计算机网络安全及防护毕业设计论文01 16页 本资源提供全文预览 点击全文预览即可全文预览 如果喜欢文档就下载吧 查找使用更方便哦 14 9 积分 掩聋邀詹手免驱闷圭刽灶开谚楞涉弓陌村娠镍淖厕绍楔聚潍理娶咐穿哦砒铰飞议纹妇苛捂鲁绽舰赚蹄奴募
  • Acwing 291. 蒙德里安的梦想

    题目分析 摆放方块的时候 先放横着的 再放竖着的 总方案数等于只放横着的小方块的合法方案数 如何判断 当前方案数是否合法 所有剩余位置能否填充满竖着的小方块 可以按列来看 每一列内部所有连续的空着的小方块需要是偶数个 这是一道动态规划的题目