【动态规划题目讲解】AGC026D - Histogram Coloring

2024-02-25 23:28

本文主要是介绍【动态规划题目讲解】AGC026D - Histogram Coloring,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[ A G C 026 D ] H i s t o g r a m C o l o r i n g \mathrm{[AGC026D] Histogram\ Coloring} [AGC026D]Histogram Coloring

D e s c r i p t i o n \mathrm{Description} Description

给定 N N N 列的网格,每列高为 h i h_i hi,将每个格子染色成红色或蓝色,使得每个 2 × 2 2\times 2 2×2 的区域都恰好有两个蓝格子和两个红格子,求方案数。

S o l u t i o n \mathrm{Solution} Solution

为了小编书写方便,令 1 1 1 为红, 0 0 0 为蓝(反过来也无所谓)

简化版

思考一下如果 h i h_i hi 全部相等,怎么做呢?(比如说,给个 20 p t s 20\mathrm{pts} 20pts 的部分分)

那么,其实就相当于给定了一个矩形,此时对于矩形的最后一行进行分类讨论:

最后一行有 2 2 2 0 0 0,那么上一行对应位置只能填 2 2 2 1 1 1,对应这别的位置也能相应的填好

所以,发现其实是一个翻转操作,但是这里的前提是下面有一对连续的 0 0 0,那么才会固定上一行,那如果最后一行是 01 01 01 交替呢?

那么,上一行你可以发现有 2 2 2 种填法: 010101 … 010101\dots 010101 1010101 … 1010101\dots 1010101

这样对于每一行都会分成 2 2 2 种,那么最后的方案数应该就是 2 h i 2^{h_i} 2hi(最后一行也是 2 2 2 种)。

而对于第 1 1 1 种情况:底部的状态有 2 n 2^n 2n 种填法,而上面会固定,所以不会再有更多的状态

但是,这 2 2 2 种会算重,即 0101 … 0101\dots 0101 1010 … 1010\dots 1010 会被算 2 2 2 次,所以最终的方案数为 2 n + 2 h i − 2 2^n+2^{h_i}-2 2n+2hi2


那么,这是简化版的做法,不过可以借鉴简化版的思路来解决这道问题。

这道题无非就是 h i h_i hi 不相同了,比如说形状如下图所示:( h i h_i hi 可能为 0 0 0

那么,对于这个图,考虑到每次可以划分成一个矩形,考虑子问题,比如说:

只考虑到当前最矮的那个方块,那么下面其实就是一个矩形,然后上面就会分成 2 2 2 个部分,即为两个子问题,那么就可以设计 DP 了!较为自然的想到设 f l , r f_{l,r} fl,r 表示区间 l ∼ r l\sim r lr 的方案数,不过只设这些可以吗?其实是不可以的,你会发现还有划分的高度,所以还要存一维高度,以及当前是不是 01 01 01 交替。所以,总结一下,设 f l , r , h , 0 / 1 f_{l,r,h,0/1} fl,r,h,0/1 表示区间 l ∼ r l\sim r lr,当前划分高度为 h h h,是/不是 01 01 01 交替。( 0 0 0 表示是, 1 1 1 表示不是)

那么,考虑转移: f l , r , h , 0 = f l , p − 1 , h p , 0 × f p + 1 , r , h p , 0 × 2 h p − h f_{l,r,h,0}=f_{l,p-1,h_p,0}\times f_{p+1,r,h_p,0}\times 2^{h_p-h} fl,r,h,0=fl,p1,hp,0×fp+1,r,hp,0×2hph

其中 p p p 为当前最低方块的位置,即左边的方案数乘右边的方案数,由于划分出的矩形是 01 01 01 交替的,所以每行都有 2 2 2 种,总共就是 2 h p − h 2^{h_p-h} 2hph 种。

下面考虑不是 01 01 01 交替的转移:

如果左侧是 01 01 01 交替,右侧是 01 01 01 交替,那么总共有 6 6 6 种,因为中间 p p p 位置要想让区间 l ∼ r l\sim r lr 不是 01 01 01 交替,那么必须和左侧或右侧中有一个是相等的。(这里就不一一列举了)

如果左侧 01 01 01 交替,右侧不是 01 01 01 交替,那么左侧可以是 01 01 01 10 10 10 p p p 位置有 2 2 2 种选择,所以是 4 4 4 种。

如果左侧不是 01 01 01 交替,右侧是 01 01 01 交替,那么同理可得是 4 4 4 种。

如果左侧和右侧都不是 01 01 01 交替,那么只能 p p p 点取 0 / 1 0/1 0/1,是 2 2 2 种。

综上所述:令 l 0 = f l , p − 1 , h p , 0 , l 1 = f l , p − 1 , h p , 1 , r 0 = f p + 1 , r , h p , 0 , r 1 = f p + 1 , r , h p , 1 l_0=f_{l,p-1,h_p,0},l_1=f_{l,p-1,h_p,1},r_0=f_{p+1,r,h_p,0},r_1=f_{p+1,r,h_p,1} l0=fl,p1,hp,0,l1=fl,p1,hp,1,r0=fp+1,r,hp,0,r1=fp+1,r,hp,1

则, f l , r , h , 1 = 6 l 0 r 0 + 4 l 0 r 1 + 4 l 1 r 0 + 2 l 1 r 1 f_{l,r,h,1}=6l_0r_0+4l_0r_1+4l_1r_0+2l_1r_1 fl,r,h,1=6l0r0+4l0r1+4l1r0+2l1r1


A c c p e t e d C o d e \mathrm{Accpeted\ Code} Accpeted Code

#include <bits/stdc++.h>
#define int long longusing namespace std;typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ull;const int SIZE = 1e2 + 10, MOD = 1e9 + 7;int N;
int H[SIZE];int ksm(int a, int b, int p)
{int Result = 1;while (b){if (b & 1) Result = Result * a % p;a = a * a % p;b >>= 1;}return Result;
}
int DP(int l, int r, int h, int k)
{if (l > r) return 1;if (l == r) return k ? 0 : ksm(2, H[l] - h, MOD);int Min = 1e18, P;for (int i = l; i <= r; i ++)if (H[i] < Min) Min = H[i], P = i;if (!k) return DP(l, P - 1, H[P], 0) * DP(P + 1, r, H[P], 0) % MOD * ksm(2, H[P] - h, MOD) % MOD;if (P == l) return 2 * (DP(P + 1, r, H[P], 0) + DP(P + 1, r, H[P], 1)) % MOD;if (P == r) return 2 * (DP(l, P - 1, H[P], 0) + DP(l, P - 1, H[P], 1)) % MOD;int L0 = DP(l, P - 1, H[P], 0), L1 = DP(l, P - 1, H[P], 1), R0 = DP(P + 1, r, H[P], 0), R1 = DP(P + 1, r, H[P], 1);return (6 * L0 % MOD * R0 % MOD + 4 * L1 * R0 % MOD + 4 * L0 * R1 % MOD + 2 * L1 * R1 % MOD) % MOD;
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);cin >> N;for (int i = 1; i <= N; i ++)cin >> H[i];cout << (DP(1, N, 0, 0) + DP(1, N, 0, 1)) % MOD << endl;return 0;
}

这篇关于【动态规划题目讲解】AGC026D - Histogram Coloring的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

基于Canvas的Html5多时区动态时钟实战代码

《基于Canvas的Html5多时区动态时钟实战代码》:本文主要介绍了如何使用Canvas在HTML5上实现一个多时区动态时钟的web展示,通过Canvas的API,可以绘制出6个不同城市的时钟,并且这些时钟可以动态转动,每个时钟上都会标注出对应的24小时制时间,详细内容请阅读本文,希望能对你有所帮助...

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计