论斜率优化dp

论斜率优化dp

  • 1问题
  • 2暴力算法-线性dp
  • 3斜率优化线性dp
  • 4后记

1问题

如下图
在这里插入图片描述
在这里插入图片描述
看到这题,题面很复杂
其实可以转化为如下问题
在这里插入图片描述
n n n个任务,排成一个有序序列,我们要解决这些任务
总费用是每一个任务的完成时间乘以费用系数求和
每个任务之前需要有一个机器启动时间 s s s
也就是说,一开始的时间为 0 0 0,做每个任务之前要先费 s s s的时间启动机器,做每个任务都需要一定时间,假设在 t i ti ti时刻完成费用系数为 f i fi fi的任务,这个任务的费用为 t i × f i ti \times fi ti×fi
总费用为 ∑ t i × f i \sum ti\times fi ti×fi
但是呢,我们可以把若干个任务并做一个,费用系数,完成耗时都求和,只是不需要多次启动机器了
这一看就是线性dp问题, 5000 5000 5000的数据范围也可以支持 n 2 n^2 n2算法

2暴力算法-线性dp

状态的设置很简单,设 d p i dp_i dpi为做完前 i i i个任务的最短耗时
怎么转移,首先枚举 d p j dp_j dpj
d p j dp_j dpj转移到 d p i dp_i dpi需要加些什么?
首先,加上机器启动时间,我们直接把之后所有的费用系数求和再乘以机器启动时间,这就是无后效性
然后,我们考虑 j + 1 j+1 j+1 i i i的任务合并,所有耗时求和再乘上费用系数求和
因为之前任务已经花费的时间会算到当前任务上,且启动机器时间已经算过了
我们把 1 − i 1-i 1i的所有任务耗时求和乘以费用系数即可
上述内容频繁用到求和,可以使用前缀和优化
这个程序很简单,直接附代码(c++)

#include<bits/stdc++.h>
using namespace std;
int n,s;
int t[114514],c[114514];
long long dp[114514],sumt[114514],sumc[114514];
int main(){memset(dp,0x3f,sizeof(dp));dp[0] = 0;cin>>n>>s;for(int i = 1;i<=n;i++){cin>>t[i]>>c[i];sumt[i] = sumt[i-1]+t[i];sumc[i] = sumc[i-1]+c[i];}for(int i = 1;i<=n;i++){for(int j = 0;j<i;j++){dp[i] = min(dp[i],dp[j]+sumc[i]*sumt[i]+s*sumc[n]-sumc[j]*(sumt[i]+s));}}cout<<dp[n];return 0;
}

你会发现你AC了,算法的复杂度 n 2 n^2 n2,是正确的
但是这是一道蓝题,肯定不止这点

3斜率优化线性dp

我们发现,枚举 i i i必然不可避免,但是枚举 j j j就多余了
我们如果能像单调队列优化dp那样直接省去枚举该多好
从状态转移方程入手
先观察
d p [ i ] = d p [ j ] + s u m c [ i ] ∗ s u m t [ i ] + s ∗ s u m c [ n ] − s u m c [ j ] ∗ ( s u m t [ i ] + s ) dp[i] = dp[j]+sumc[i]*sumt[i]+s*sumc[n]-sumc[j]*(sumt[i]+s) dp[i]=dp[j]+sumc[i]sumt[i]+ssumc[n]sumc[j](sumt[i]+s)
移项得
d p [ j ] = ( s u m t [ i ] + s ) ∗ s u m c [ j ] + d p [ i ] − s u m t [ i ] ∗ s u m c [ i ] − s ∗ s u m c [ n ] dp[j] = (sumt[i]+s)*sumc[j]+dp[i]-sumt[i]*sumc[i]-s*sumc[n] dp[j]=(sumt[i]+s)sumc[j]+dp[i]sumt[i]sumc[i]ssumc[n]
很容易发现, ( s u m t [ i ] + s ) (sumt[i]+s) (sumt[i]+s) ( d p [ i ] − s u m t [ i ] ∗ s u m c [ i ] − s ∗ s u m c [ n ] ) (dp[i]-sumt[i]*sumc[i]-s*sumc[n]) (dp[i]sumt[i]sumc[i]ssumc[n])固定,在枚举 j j j的时候,变化的只有 d p [ j ] dp[j] dp[j] s u m c [ j ] sumc[j] sumc[j],这不就是一次函数吗, y = k x + b y = kx+b y=kx+b,那么,要让dp[i]尽可能小
d p [ j ] dp[j] dp[j] ( s u m t [ i ] + s ) ∗ s u m c [ j ] (sumt[i]+s)*sumc[j] (sumt[i]+s)sumc[j]就要尽量接近
我们试着画图
在这里插入图片描述
哪个点距离一次函数最近就很明显了
那这有啥用呢
我们可以删去部分点了
用不同斜率的直线尝试求解,删去没有用的点
在这里插入图片描述
显然的,一个下凸包,我们动态维护凸包,这样就有了单调性
那么哪个点离直线最近呢,显然是连接两条斜率分别大于和小于当前直线的线段的点
这就可以跑二分了
时间复杂度 n l o g n nlogn nlogn,快了很多
还能再快吗,可以!
我们发现所有费用系数都是正整数, s s s也不变,那么前缀和即 s u m c sumc sumc必然单调递增
直线的斜率也自然是单调递增
这就可以用单调队列维护了,斜率单调递增就行
对于新插入的点,肯定是斜率越小越好,这下动态维护下凸包也可以一并解决
斜率的比较最好交叉相乘,避免误差
附代码(c++)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300010;
int n,s;
LL c[N],t[N];
LL dp[N];
int q[N];
int main(){cin>>n>>s;for(int i = 1;i<=n;i++){cin>>t[i]>>c[i];t[i]+=t[i-1];c[i]+=c[i-1];}int hh = 0,tt = 0;dp[0] = 0;for(int i = 1;i<=n;i++){while(hh<tt&&((dp[q[hh+1]])-dp[q[hh]])<=(t[i]+s)*(c[q[hh+1]]-c[q[hh]])){hh++;}int j = q[hh];dp[i] = dp[j]-(t[i]+s)*c[j]+t[i]*c[i]+s*c[n];while(hh<tt&&((dp[q[tt]])-dp[q[tt-1]])*(c[i]-c[q[tt]])>=(dp[i]-dp[q[tt]])*(c[q[tt]]-c[q[tt-1]])){tt--;}q[++tt] = i;}cout<<dp[n];return 0;
}

4后记

斜率优化代表着本蒟蒻动态规划系列作品的结束
之后还会有插头dp,四边形不等式等内容
不过我太蒻了暂时学不会
本文作者是蒟蒻,如有错误请各位神犇指点
森林古猿出品,必属精品,请认准CSDN森林古猿1

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

sessionstorage和localstorage的使用与区别

sessionstorage和localstorage的使用与区别 localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。他们均只能存储字符串类型的对象&#xff08;虽然规范中可以存储其他原生类型的对象&#xff0c;但是目前为止没有浏览器对其进行实现&#xff09;。 localStor…

Hadoop 下载

下载法一&#xff1a;官方下载 hadoop官网 1.选择要下载的版本&#xff0c;这里我以3.4.0为例进行说明&#xff1b; 2.跳转后&#xff0c;选择对应系统架构的&#xff0c;进行下载&#xff1b; 下载法二&#xff1a;国内镜像源下载 1.阿里云 这里我以mac m1为案例&#x…

Linux日志-wtmp日志

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux 系统中的日志是记录系统活动和事件的重要工具&#xff0c;它们可以帮助管理员监视系统状态、调查问题以及了解系统运行…

【保姆级教程】如何在Win11上搭建一个GPU环境

CUDA和CUDNN安装 CUDA安装 下载对应cuda环境 下载链接&#xff1a;https://developer.nvidia.com/cuda-downloads&#xff0c;图片下载的是 cuda_12.6.1_560.94_windows.exe 然后一路安装即可&#xff1a; 安装路径如下&#xff1a; CUDNN安装 打开cuDNN下载页面 解压后…

嵌入式基础知识-RS232通信协议电路与代码最全分析

1.RS232基本概念 RS232是异步通信&#xff0c;全双工传输&#xff08;异步通信就是无时钟CLK信号&#xff0c;全双工就是能同时收发数据&#xff09;。采用负逻辑传送&#xff0c;规定逻辑“1”的电平为-5V~-15 V&#xff0c;逻辑“0”的电平为5 V&#xff5e;15 V。选用该电气…

阻塞队列-单锁实现

使用阻塞队列 当我们多个线程下 对 一个队列进行操作&#xff0c;队列满了的情况下&#xff0c;其他线程再次 offer&#xff0c;会一直阻塞等待 对一个队列进行出队操作的时候&#xff0c;队列空的情况下&#xff0c;会一直阻塞等待删除&#xff0c;直到队列有元素的时候&a…

C++刷怪笼(2)类和对象的探索-上

1.前言 了解完C的一些入门干货之后&#xff0c;我们来对C的第一个重点就行学习——那就是类和对象&#xff0c;该重点我们分为三篇文章进行学习&#xff0c;请大家跟紧我的脚步&#xff0c;认真学知识哦~ 2.正文——类和对象 2.1类的定义 2.2.1类的定义格式 • class为定义…

echarts遍历区域折线图,单线和多线

// 单线折线图drawonelineCharts(){var echarts require("echarts");var lineCharts document.getElementsByClassName(lineChart); // 对应地使用ByClassNamethis.linecolor[#01FFD4,#1C70DD,#01FFD4,#1C70DD,#01FFD4,#1C70DD]for(var i 0;i < lineCharts.len…

内核头文件, makfile 传参

1 内核头文件&#xff0c;主要指的是&#xff0c; 在板卡上的系统上直接 &#xff0c;编译驱动模块&#xff0c;而不是在虚拟机的内核源码中 去编译内核模块。 2 makefile 传参 &#xff0c;指的是&#xff0c; 内核模块使用 makfile 定义的宏定义。 首先是 关于 在普通的makef…

ubuntu24安装cuda和cudnn

一、安装cuda 确保显卡驱动正确安装 终端输入&#xff1a; nvidia-smi显示下面结果&#xff0c;说明显卡驱动安装正常&#xff0c;可以进行下一步 1.去官网下载CUDA&#xff0c;需要注册账号下载 https://developer.nvidia.com/cuda-toolkit-archive由于我们显卡支持12.2&…

网络通信特刊合集(二)——CMC特刊推荐

特刊征稿 01 特刊名称&#xff1a; Security and Privacy for Blockchain-empowered Internet of Things 截止时间&#xff1a; 提交截止日期 2024 年 10 月 30 日 目标及范围&#xff1a; 本期特刊旨在探讨最近的进展&#xff0c;以解决在区块链授权的物联网中与安全和…

一文带你深度了解FreeRTOS——计数型信号量

本文记录FreeRTOS的计数型信号量知识&#xff0c;希望我的分享对你有所帮助&#xff01; 目录 一、计数型信号量简介 二、创建计数型信号量 1、动态创建计数型信号量 2、静态创建计数型信号量 三、结语 一、计数型信号量简介 计数型信号量在FreeRTOS中用于管理对共享资…

拥有这些AI绘画网站,让你轻松告别手绘时代!

在这个充满无限可能的数字世界里&#xff0c;AI 绘画动漫网站已经成为了许多艺术家和设计师的新宠。从手绘时代的岁月如歌&#xff0c;到今天科技的飞速发展&#xff0c;我们已经可以用AI技术创作出令人惊叹的艺术作品&#xff0c;打开了全新的创作空间。接下来&#xff0c;就让…

如何打造一个智能化的远程在线考试系统?

远程教育与在线考试已成为提升知识传播效率和学习灵活性的重要手段。 土著刷题在线考试系统&#xff0c;凭借其完善的多功能考试模块&#xff0c;为教育机构、学校乃至企业提供了一个智能化的远程在线考试解决方案。 接下来将介绍土著刷题在线考试系统如何助力用户构建一个高效…

小琳Python课堂:Python 高并发实现的基本原理(简化版)

大家好&#xff0c;这里是小琳Python课堂&#xff01; 今天&#xff0c;我们来聊聊Python中实现高并发的三个核心概念&#xff1a;线程安全性、线程同步和原子性。这些概念对于确保我们的程序在多线程环境中正确、高效地运行至关重要。 线程安全性 首先&#xff0c;什么是线程…

51单片机-串口通信(单片机和PC互发数据)

作者&#xff1a;Whappy 时间&#xff1a;2024.9.3 关于串口的疑问&#xff1f; 根据我的代码是不是初始化完成串口之后&#xff0c;只要我们使用串口发送数据就会触发中断&#xff1f; &#xff08;在文章下面&#xff09; ChatGPT said: ChatGPT 是的&#xff0c;根据…

[AWS云]EC2扩容磁盘之linux系统

背景&#xff1a; ec2的磁盘存储满了&#xff0c;需要扩容。 1.控制台修改存储大小&#xff1a; 2. 3.登录服务器&#xff0c;刷新磁盘&#xff1a; 云盘扩容 growpart /dev/vdb 1对ext4扩容命令resize2fs /dev/vdb1对xfs扩容命令xfs_growfs /dev/vdc1

传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统&#xff0c;其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术&#xff0c;自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述&#xff1a; 1. 导入必要的库 系统首先导入…

openlayers+vite+vue3实现规划某一特定行政区(二)

在前一期实现离线地图初始化的基础上&#xff0c;本文中主要阐述如何实现规划某一特定行政区&#xff0c;并展示其行政区的区县名称。 提示&#xff1a;因前文中阐述了如何实现离线地图的初始化&#xff0c;所以在此不再进行书写并详解初始化的过程和流程&#xff0c;如有不明…

MySQL简介和管理

目录 一、数据库基本概念 1.1、数据 1.2、表 1.3、数据库 1.4、数据库管理系统 1.5、数据库系统 二、数据库发展史 2.1、第一代数据库 2.2、第二代数据库 2.3、第三代数据库 三、数据库类型 3.1、关系型数据库 3.2、关系型数据库应用 3.3、非关系型数据库 3.4、…