【Acwing291】蒙德里安的梦想(状态压缩dp)详细讲解

题目描述

题目分析

显而易见的重要事实

首先,需要明白一个很重要的事实:

所有的摆放方案数=所有横着摆放且合理的方案数

这是因为,横着的确定之后,竖着的一定会被唯一确定,举一个例子:

------唯一确定----->

所以使用动态规划进行状态表示的时候,仅仅需要考虑横着的长方形即可

状态表示

随后,我们来看状态表示:

f[i,j]表示:前i-1列已经摆好,且从第i-1列伸出到第i列的状态为j的所有方案数

注意:列数的下标是0~m-1

举一个例子:

 如上图,假设一个6*6棋盘,前两列已经以如图方式摆好,此时对于第三列的第一、四行有被第二列伸过来的部分,所以此时第二列的状态就是100100,将这个字符串看成二进制数,转为十进制为36,所以这就是f[2,36]所指的“所有方案数”的其中一个。

状态计算

对于同一列i,即使j值(状态数)相同,也会因为前i-1列的摆放方案不同而导致整体的摆放方案不同,也就是说,在前i-1列已经确定的情况之下,第i-1列的每一个状态的每一个方案都能够组合一个第i列的确定的状态j得到一个新的摆放方案:

比如上述这个图,列3的状态为:101010,由于列2可能存在不同的状态(0x0y0z),导致整体的摆放方案不同,同理,列2的某一种状态的方案数也因为列1可能存在不同的状态导致此方案数有可能大于1,所以呈现一个递归的现象,由此可得状态计算:

f[i,j]=\sum f[i-1,k]  

其中k为第i-1列的状态值,可以取不同的值

何时合理

显然,对于上述状态计算式子,如果不限制k值和j的关系,而一味地让k和j取遍整个0~2^n-1,就会发生一些不合理的现象,比如:

假设现在已经处理到i=3的情况,并且假设i=0~i=2的所有长方形已经摆好,就会发现两个不合理的现象:

1.在第一行的列2和列3地方发生了交叉

2.第二行的列2位置有一个不合理空缺,这个位置无法再填补任何的长方形,因为现在已经假定0~2列是摆好的,不会再去这个位置填补空缺的横着放的长方形,同时这个地方也根本不可能去放置竖长方形。

为什么产生了这个现象?

因为没有约束k和j的关系

我们先来看第一个不合理之处产生的原因:(k&j)!=0

顺便注意一下这里,k&j一定要加括号,因为!=的优先级大于&

因为如果k&j!=0,那么至少存在一行使得i和i-1列中同时有从i-1和i-2列伸过来的长方形,从而导致长方形的重叠

第二个不合理之处的产生原因:i-1列中的连续的空缺位置中存在空缺大小为奇数的情况

如何避免这个不合理之处呢?

保证:st[j|k]==true,其中st[x]为true的条件是x的二进制表示中没有奇数个连续的0

边界问题

开头已经说过了,此题列的表示下标从0开始,所以初始化为f[0][0]=1,意思是“没有从左边的棋盘边界的外边伸向第一列的长方形的方案数为1”,其它f全部初始化为0。

如果列数为m,列号从0开始,在遍历i的时候,最后遍历到的下标是m而不是m-1,因为当遍历到第i列的时候,实际上保证的是第i-1列的合法性,比如,刚才那个例子:

当遍历到i=3的时候,发现的两个不合理之处全在i=2列。

最后的答案为:f[m][0],意思是“在0~m-1列全部摆好的情况之下,棋盘右边界的右边一列没有第m列伸过来的长方形的总方案数”

朴素代码以及短路现象

#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 12, M = 1 << N;int n, m;
long long f[N][M];
bool st[M];int main()
{while (cin >> n >> m, n || m){for (int i = 0; i < 1 << n; i ++ ){int cnt = 0;st[i] = true;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;}memset(f, 0, sizeof f);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;
}

在上y总的课时,y总说这个代码有一个神奇的现象,就是把(j & k) == 0 && st[j | k]中&&前后的部分进行交换之后,时间会变长许多,此代码从892ms变为1442ms,很显然这与&&的短路性有关,当

(j & k) == 0不满足时,就会跳过st[j | k]的判断,因为(j & k) == 0的“成功率”小于“st[j | k]”的成功率,所以会出现上述现象。

优化之后的代码

此代码已经经过优化:预处理去除无效状态

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N=12,M=1<<N;
typedef long long LL;
LL f[N][M];
bool st[M];
vector<int>state[M];//存放j和k的合法映射的集合
int n,m;
int main()
{while(scanf("%d%d",&n,&m)==2&&(n||m)){for(int i=0;i<1<<n;i++)//st数组的预处理{int cnt=0;st[i]=true;for(int j=0;j<n;j++){if(i>>j&1){if(cnt&1){st[i]=false;break;}cnt=0;}else cnt++;}if(cnt&1)st[i]=false;}for(int j=0;j<1<<n;j++){state[j].clear();//为什么要清空?因为是多样例输入for(int k=0;k<1<<n;k++)if((k&j)==0&&st[k|j])state[j].push_back(k);//满足推出f[i][j]的第i-1行的其中一个状态数k}memset(f,0,sizeof f);//因为是多样例输入f[0][0]=1;for(int i=1;i<=m;i++){for(int j=0;j<1<<n;j++)for(auto k:state[j])//代码优化的体现,大大减少了冗余f[i][j]+=f[i-1][k];}cout<<f[m][0]<<endl;}return 0;
}

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/106951.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ---订阅模型-Fanout

1、 订阅模型-Fanout Fanout&#xff0c;也称为广播。 流程图&#xff1a; 在广播模式下&#xff0c;消息发送流程是这样的&#xff1a; 1&#xff09; 可以有多个消费者 2&#xff09; 每个消费者有自己的queue&#xff08;队列&#xff09; 3&#xff09; 每个队列都要绑定…

Windows 10【压缩卷】操作报错【无法将卷压缩到超出任何不可移动的文件所在的点】的解决方法

目录 一、背景 二、原因 三、解决方法 3.1 Windows自带的碎片清理工具 3.1.1 操作步骤 3.1.2 操作结果 3.2 MyDefrag工具清理磁盘碎片 3.2.1 操作步骤 3.2.2 操作结果 3.3 Windows自带的事件查看器 3.3.1 操作步骤 3.3.2 操作结果 3.4 关闭虚拟内存并删除虚拟内存…

离谱事件解决方法2 无法定位程序输入点XXX于动态链接库XXX.dll

事情经过&#xff1a; 本人一只acmer&#xff0c;使用sublime编写代码&#xff0c;但是前两天在打开cpp类型的文件的时候显示报错如下&#xff1a; 这里的dll文件就是动态链接库&#xff0c;它并不是一个可执行文件&#xff0c;里面存放的是程序的函数实现过程&#xff08;公用…

django+MySQL计算机毕设之图片推荐系统(报告+源码)

图片推荐系统是在的数据存储主要通过MySQL。用户在使用应用时产生的数据通过Python语言传递给数据库。通过此方式促进图片推荐信息流动和数据传输效率&#xff0c;提供一个内容丰富、功能多样、易于操作的平台。述了数据库的设计&#xff0c;系统的详细设计部分主要论述了几个主…

Ubuntu释放VMware虚拟磁盘未使用空间

By: Ailson Jack Date: 2023.08.26 个人博客&#xff1a;http://www.only2fire.com/ 本文在我博客的地址是&#xff1a;http://www.only2fire.com/archives/152.html&#xff0c;排版更好&#xff0c;便于学习&#xff0c;也可以去我博客逛逛&#xff0c;兴许有你想要的内容呢。…

面试之快速学习计算机网络-http

1. HTTP常见状态码 2. 3开头重定向&#xff0c;4开头客户端错误&#xff0c;5开头服务端错误 2. HTTP 报文 1. start-line&#xff1a;请求行&#xff0c;可以为以下两者之一&#xff1a; 请求行&#xff1a; GET /hello-world2.html HTTP/1.1状态行&#xff1a;HTTP/1.1 200…

YOLOv8教程系列:三、K折交叉验证——让你的每一份标注数据都物尽其用(yolov8目标检测+k折交叉验证法)

YOLOv8教程系列&#xff1a;三、K折交叉验证——让你的每一份标注数据都物尽其用&#xff08;yolov8目标检测k折交叉验证法&#xff09; 0.引言 k折交叉验证&#xff08;K-Fold Cross-Validation&#xff09;是一种在机器学习中常用的模型评估技术&#xff0c;用于估计模型的性…

JavaScript(笔记)

目录 Hello World JavaScript 的变量 JavaScript 动态类型 隐式类型转换 JavaScript 数组 JavaScript 函数 JavaScript 中变量的作用域 对象 DOM 选中页面元素 事件 获取 / 修改元素内容 获取 / 修改元素属性 获取 / 修改 表单元素属性 获取 / 修改样式属性 新…

Java版B/S架构 智慧工地源码,PC、移动、数据可视化智慧大屏端源码

智慧工地是什么&#xff1f;智慧工地主要围绕绿色施工、安全管控、劳务管理、智能管理、集成总控等方面&#xff0c;帮助工地解决运营、管理方面各个难点痛点。在互联网的加持下促进项目现场管理的创新与发展&#xff0c;实现工程管理人员与工程施工现场的整合&#xff0c;构建…

[机缘参悟-102] :IT人 - 管理的本质?管理人与从事技术的本质区别?人性、冰山模型、需求层次模型

感悟&#xff1a; 管理的本质是&#xff1a;学习各种管理理论、方法、技能&#xff0c;克服自身的人性缺点、预防他人人性的恶点、利用他人的人性特点拿到结果&#xff0c;从而完成组织、管理者的上司、管理者自身、管理者下属的目标。管理中的问题&#xff0c;80%以上都人性问…

rtmp直播

技术要求&#xff1a;nginxnginx-rtmpffmpegVLC 跟着大佬走的&#xff1a; 传送门 准备工作&#xff1a; 首先需要一台公网ip的服务器 这是使用天翼云的弹性云主机&#xff1a;免费试用1个月 天翼云官网 点击关机&#xff0c;更多里面选择重置密码&#xff0c; 默认用户名为…

根据案例写PLC程序-红绿灯控制

案例&#xff1a; 1、南北方向红灯点亮30s后熄灭&#xff1b; 2、在点亮南北方向红灯的同时点亮东西方向绿灯&#xff0c;并在点亮25s后&#xff0c;以0.5s熄灭0.5s点亮的时间闪烁3次后熄灭&#xff1b; 3、在东西方向绿灯熄灭后&#xff0c;东西方向黄灯点亮2s后熄灭&#xff…

数据库的增量备份与差异备份

在当今数字时代&#xff0c;数据已经成为公司的主要资产。为了维护这些珍贵的数据&#xff0c;公司通常会采取各种数据保护措施&#xff0c;其中增量备份是一种很有效的方法。本文将详细介绍什么是数据库的增量备份&#xff0c;以及如何帮助企业更有效地维护数据。  我们需要…

HTML+CSS 查漏补缺

目录 1&#xff0c;HTML1&#xff0c;尺寸的百分比1&#xff0c;普通元素2&#xff0c;绝对&#xff08;固定&#xff09;定位元素3&#xff0c;常见百分比 2&#xff0c;form 表单元素1&#xff0c;form2&#xff0c;button3&#xff0c;label4&#xff0c;outline5&#xff0…

Multisim软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Multisim软件是一款电路仿真和设计软件&#xff0c;由美国国家仪器公司&#xff08;National Instruments&#xff09;开发。它提供了一个交互式的图形界面&#xff0c;使用户能够轻松地构建和仿真电路。以下是Multisim软件的详…

《扩散模型 从原理到实战》Hugging Face (一)

文章目录 前言第一章 扩散模型简介1.1 扩散模型的原理1.1.1 生成模型1.1.2 扩散过程 前言 Hugging Face最近出版了第一本中文书籍《扩散模型 从原理到实战》&#xff0c;其中内容关于扩散模型&#xff08;Diffusion Model&#xff09;&#xff0c;和AIGC相关的内容较多&#x…

2023企业网盘产品排行榜揭晓:选择最适合你的企业网盘工具

企业网盘产品已成为企业文件管理协作的主要选择之一&#xff0c;无论是在文件管理方面&#xff0c;还是团队协作上&#xff0c;企业网盘都表现优秀。为了帮助企业选到心怡的企业网盘产品&#xff0c;我们综合了不同的产品测评网站意见&#xff0c;整理了2023企业网盘产品排行榜…

【游戏开发教程】Unity Cinemachine快速上手,详细案例讲解(虚拟相机系统 | 新发出品 | 良心教程)

文章目录 一、前言二、插件下载三、案例1&#xff1a;第三人称自由视角&#xff0c;Free Look character场景1、场景演示2、组件参数2.1、CinemachineBrain&#xff1a;核心2.2、CinemachineFreeLook&#xff1a;第三人称自由视角相机2.2.1、设置Follow&#xff1a;跟随2.2.2、…

phpstorm动态调试

首先在phpstudy搭建好网站&#xff0c;在管理拓展开启xdebug拓展 查看php.ini配置已经更改 需要增添修改一下设置 [Xdebug] zend_extensionD:/phpstudy_pro/Extensions/php/php5.6.9nts/ext/php_xdebug.dll xdebug.collect_params1 xdebug.collect_return1 xdebug.auto_trace…

[Open-source tool] 可搭配PHP和SQL的表單開源工具_Form tools(1):簡介和建置

Form tools是一套可搭配PHP和SQL的表單開源工具&#xff0c;可讓開發者靈活運用&#xff0c;同時其有數個表單模板和應用模組供挑選&#xff0c;方便且彈性。Form tools已開發超過20年&#xff0c;為不同領域的需求者或開發者提供一個自由和開放的平台&#xff0c;使他們可建構…