斜率优化详解

2024-06-13 11:36
文章标签 详解 优化 斜率

本文主要是介绍斜率优化详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

斜率优化

[HNOI2008] 玩具装箱

状态转移方程:
f i = m i n ( f i , f j + ( s u m i + i − s u m j − j − L ) 2 ) i > j f_i=min(f_i,f_j+(sum_i+i-sum_j-j-L)^2){i>j} fi=min(fi,fj+(sumi+isumjjL)2)i>j
设A为 s u m i + i sum_i+i sumi+i,B为 s u m j + j + L + 1 sum_j+j+L+1 sumj+j+L+1

简化可得:
f i = m i n ( f i , f j + A 2 − 2 A B + B 2 ) f_i=min(f_i,f_j+A^2-2AB+B^2) fi=min(fi,fj+A22AB+B2)
稍微分解一下,有:
f i = f j + A 2 − 2 A B + B 2 f j + B 2 = 2 A B + f i − A 2 f_i=f_j+A^2-2AB+B^2 \\ f_j+B^2=2AB+f_i-A^2 fi=fj+A22AB+B2fj+B2=2AB+fiA2
f j + B 2 f_j+B^2 fj+B2 为点 y y y 2 A 2A 2A k k k B B B x x x f i − A 2 f_i-A^2 fiA2 b b b

考虑一个确定的点 ( B , f j + B 2 ) (B,f_j+B^2) (B,fj+B2) k = 2 A k=2A k=2A​ 的最小截距。

对于每个确定的 i i i,可令斜率为 h i h_i hi 的直线过每个决策点,都可求得一个截距。根据状态转移方程可知,其中截距最小的直线方程所经过的决策点即为左右决策。

斜率:

先看一张图:

  • 斜率(↑↑↑)

斜率就是坡度,是高度的平均变化率,用坡度来刻划道路的倾斜程度,也就是用坡面的切直高度和水平长度的比,相当于在水平方向移动一千米,在切直方向上升或下降的数值,这个比值实际上就表示了坡度的大小。

即:设 ( 0 , 0 ) (0,0) (0,0) 点为 a a a ( 3 , 0 ) (3,0) (3,0) 点为 b b b,则点 B B B 的斜率为 ∣ b − a ∣ B − b \frac{|b-a|}{B-b} Bbba​。

以下称 x j x_j xj x x x 轴的 j j j 点, y i y_i yi 为在 y y y 轴的 i i i 点。

在绝v额集合中筛选出部分决策,使得在 x j x_j xj 递增的顺序下,相邻的决策点所炼成的线段的斜率单调递增。对于任意连续的三个所选决策 j i − 1 , j i , j i + 1 j_{i-1},j_{i},j_{i+1} ji1,ji,ji+1,都有:
f j i − f j i − 1 x j i − x j i − 1 < f j i + 1 − f j i f j i + 1 − f j i \frac{f_{j_{i}}-f_{j_{i-1}}}{x_{j_i}-x_{j_{i-1}}}<\frac{f_{j_{i+1}}-f_{j_{i}}}{f_{j_{i+1}}-f_{j_i}} xjixji1fjifji1<fji+1fjifji+1fji
在对应坐标系中,相邻点之间连成的线段呈现出“下凸”形态,即为“凸包”。

  • 凸包(↑↑↑)

若斜率函数 h i h_i hi x j x_j xj 均为单调递增函数,随着 j j j 的递增,决策点的横坐标也单调递增,新决策必定会出现在整个凸包的最右端。又因为斜率函数具有单调性,所以每次需要求解的直线斜率 h i h_i hi 也单调递增。决策集合仅保留下凸曲线上相邻现代斜率大于 h i h_i hi 的剩余决策点,所以曲线最左端的决策点即为最优决策。

  • 最优决策、最优斜率、截距(设B点为最佳决策点)

根据如上性质,我们不难想出,用双端队列 q[l~r] 维护下凸曲线,队列中保存部分决策,对应下凸曲线上的决策点,满足 x i x_i xi​ 和 h i h_i hi​​ 都递增。

具体实施方案:
  • 为了保证队头即为最优决策,仅需保留下凸曲线上斜率大于 h i h_i hi 的点,从队头开始检查决策 q l q_l ql 和后续决策 q l + 1 q_{l+1} ql+1 对应点连接线的斜率。若该斜率小等于 h i h_i hi,则把 q l q_l ql 出队,继续检查寻得队头和后续决策,直至线段斜率大于 h i h_i hi
  • 直接取队头决策 j = q l j=q_l j=ql 为最优决策,进行状态转移。
  • 将当前状态 i i i 为新的决策从队尾插入。在插入前需要维护凸曲线性质,即三个决策点 q r − 1 , q r , i q_{r-1},q_r,i qr1,qr,i 对应的相邻线段需要满足斜率单调递增,否则吧决策 q r q_r qr 出队,继续检查 q r − 2 , q r − 1 , i q_{r-2},q_{r-1},i qr2,qr1,i,直至满足要求。设此操作一共进行了 n n n 轮,则最终需要判断的三个状态为 q r − n , q r − n + 1 , i q_{r-n},q_{r-n+1},i qrn,qrn+1,i

时间复杂度: O ( N ) O(N) O(N)

  • 若斜率函数 h i h_i hi 不满足单调性,则 x j x_j xj 为单调递增函数,队头不为最优决策,须保留整个下凸曲线,可在队列中二分查找,求出一个位置 k k k,使得:

∀ p < k ∀ q > k h p < h k < h q \forall\ p\ <\ k \\ \forall\ q\ >\ k \\ h_p<h_k<h_q  p < k q > khp<hk<hq

若满足以上条件,则 k k k 为最优决策。

时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn)

AC Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,l;
const ll MAXN=5e4+5;
ll q[MAXN],sum[MAXN],f[MAXN];
ll head=1,tail=1;
ll j;
inline ll x(ll j)//x坐标 
{return sum[j];
}
inline ll y(ll j)//y坐标 
{return f[j]+(sum[j]+l)*(sum[j]+l);
}
inline double slope(ll i,ll j)//计算 
{return (double)(y(j)-y(i))/(x(j)-x(i));
}
inline ll compute(ll i,ll j)//代价公式 
{return (sum[i]-sum[j]-l)*(sum[i]-sum[j]-l);
}
int main(){scanf("%lld%lld",&n,&l);l++;//因为一直都是-l-1,干脆直接变为 -(l+1) for(ll i=1;i<=n;i++){scanf("%lld",&sum[i]);sum[i]+=sum[i-1]+1;//前缀和 }q[tail]=0;for(ll i=1;i<=n;i++)//dp{while(head<tail&&slope(q[head],q[head+1])<=(sum[i]<<1))//出队首条件 head++;j=q[head];//队首 f[i]=f[j]+compute(i,j);//计算 while(head<tail&&slope(q[tail-1],q[tail])>=slope(q[tail-1],i))//出队末条件 tail--;q[++tail]=i;//最优决策入队 }printf("%lld\n",f[n]);return 0;
}

这篇关于斜率优化详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

MySQL表空间结构详解表空间到段页操作

《MySQL表空间结构详解表空间到段页操作》在MySQL架构和存储引擎专题中介绍了使用不同存储引擎创建表时生成的表空间数据文件,在本章节主要介绍使用InnoDB存储引擎创建表时生成的表空间数据文件,对... 目录️‍一、什么是表空间结构1.1 表空间与表空间文件的关系是什么?️‍二、用户数据在表空间中是怎么

python3 pip终端出现错误解决的方法详解

《python3pip终端出现错误解决的方法详解》这篇文章主要为大家详细介绍了python3pip如果在终端出现错误该如何解决,文中的示例方法讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下... 目录前言一、查看是否已安装pip二、查看是否添加至环境变量1.查看环境变量是http://www.cppcns

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

Swagger2与Springdoc集成与使用详解

《Swagger2与Springdoc集成与使用详解》:本文主要介绍Swagger2与Springdoc集成与使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1. 依赖配置2. 基础配置2.1 启用 Springdoc2.2 自定义 OpenAPI 信息3.

mysql中的group by高级用法详解

《mysql中的groupby高级用法详解》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,本文给大家介绍mysql中的groupby... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

Spring 缓存在项目中的使用详解

《Spring缓存在项目中的使用详解》Spring缓存机制,Cache接口为缓存的组件规范定义,包扩缓存的各种操作(添加缓存、删除缓存、修改缓存等),本文给大家介绍Spring缓存在项目中的使用... 目录1.Spring 缓存机制介绍2.Spring 缓存用到的概念Ⅰ.两个接口Ⅱ.三个注解(方法层次)Ⅲ.

Spring Boot 整合 Redis 实现数据缓存案例详解

《SpringBoot整合Redis实现数据缓存案例详解》Springboot缓存,默认使用的是ConcurrentMap的方式来实现的,然而我们在项目中并不会这么使用,本文介绍SpringB... 目录1.添加 Maven 依赖2.配置Redis属性3.创建 redisCacheManager4.使用Sp

Spring Cache注解@Cacheable的九个属性详解

《SpringCache注解@Cacheable的九个属性详解》在@Cacheable注解的使用中,共有9个属性供我们来使用,这9个属性分别是:value、cacheNames、key、key... 目录1.value/cacheNames 属性2.key属性3.keyGeneratjavascriptor

PyTorch中cdist和sum函数使用示例详解

《PyTorch中cdist和sum函数使用示例详解》torch.cdist是PyTorch中用于计算**两个张量之间的成对距离(pairwisedistance)**的函数,常用于点云处理、图神经网... 目录基本语法输出示例1. 简单的 2D 欧几里得距离2. 批量形式(3D Tensor)3. 使用不

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5