斜率优化dp 笔记

任务安排1

有 N 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。

机器会把这 N 个任务分成若干批,每一批包含连续的若干个任务。

从时刻 00 开始,任务被分批加工,执行第 i 个任务所需的时间是 Ti。

另外,在每批任务开始前,机器需要 S 的启动时间,故执行一批任务所需的时间是启动时间 S 加上每个任务所需时间之和。

一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。

也就是说,同一批任务将在同一时刻完成。

每个任务的费用是它的完成时刻乘以一个费用系数 Ci。

请为机器规划一个分组方案,使得总费用最小。

输入格式

第一行包含整数 N。

第二行包含整数 S。

接下来 N行每行有一对整数,分别为 Ti 和 Ci,表示第 i 个任务单独完成所需的时间 Ti 及其费用系数 Ci。

输出格式

输出一个整数,表示最小总费用。

数据范围

1≤N≤5000,
0≤S≤50,
1≤Ti,Ci≤100

输入样例:
5
1
1 3
3 2
4 3
2 3
1 4
输出样例:
153

 f[i]表示选好前i个任务的最小值

关键点在于把每次开始的S时间造成的全部后续影响加到当前这次的操作中,这样就不用考虑之前启动了几次机器了,取消了后效性

虽然过程中的f[1~n-1]的设计的值与状态设计不一定相同但f[n]一定是相同的 

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef pair<int, int> PII;
typedef long long ll;

const int N = 5010;

int n, S;
ll T[N], C[N], sum[N];
ll f[N];

int main()
{
	IOS
	cin >> n >> S;
	for(int i = 1; i <= n; i ++)cin >> T[i] >> C[i];
	for(int i = 1; i <= n; i ++)
	{
		sum[i] = sum[i - 1] + C[i];
		T[i] += T[i - 1];
	}
	
	for(int i = 1; i <= n; i ++)
	{
		f[i] = 2e18;
		for(int j = 1; j <= i; j ++)//[j, i]
		{
			//关键点在于把每次开始的S时间造成的全部后续影响加到当前这次的操作中
			//虽然过程中的f[1~n-1]的设计的值与状态设计不一定相同但f[n]一定是相同的 
			ll res = f[j - 1] + T[i] * (sum[i] - sum[j - 1]) + S * (sum[n] - sum[j - 1]);
			f[i] = min(f[i], res);
		}
	}
	cout << f[n];
	
	return 0;
}

任务安排2

有 N个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。

机器会把这 N 个任务分成若干批,每一批包含连续的若干个任务。

从时刻 0 开始,任务被分批加工,执行第 i 个任务所需的时间是 Ti。

另外,在每批任务开始前,机器需要 S 的启动时间,故执行一批任务所需的时间是启动时间 S 加上每个任务所需时间之和。

一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。

也就是说,同一批任务将在同一时刻完成。

每个任务的费用是它的完成时刻乘以一个费用系数 Ci。

请为机器规划一个分组方案,使得总费用最小。

输入格式

第一行包含整数 N。

第二行包含整数 S。

接下来 N 行每行有一对整数,分别为 Ti 和 Ci,表示第 i 个任务单独完成所需的时间 Ti 及其费用系数 Ci。

输出格式

输出一个整数,表示最小总费用。

数据范围

1≤N≤3×1e5,
1≤Ti,Ci≤512,
0≤S≤512

输入样例:
5
1
1 3
3 2
4 3
2 3
1 4
输出样例:
153

 除了数据范围其余和上一题一样

把j - 1看为 j可推出的公式:f[i]=f[j]+T[i]*(C[i]-C[j])+S*(C[n]-C[j])

可以发现当i固定时f[i]、C[i]、T[i]为定值,有两个未知量C[j]和f[j]

设f[j]为y,C[j]为x,整理一下式子

f[j]=(T[i] + S) * C[j] + f[i] - T[i]*C[i] - S*C[n]

约等于y = kx + b

可以发现截距b越小f[i]就越小,此时便来到了真正的斜率优化

找到下面最外围的凸包,找到第一个斜率大于k的那条边的左端点,此点就是在k斜率下到达y轴时最低的那个点(因为k>0° && k < 90°)

找这个凸包的办法:取出后两个点(x1,y1),(x2,y2)与当前点(x3,y3)比,如果第一个点和第二个点的斜率大于第一个点和第三个点的斜率就删掉最后一个点。循环往复。最后再加进这个点。

一般来说是用二分去找的

但这题还有点小性质,就是斜率k在不断变大,因此可以用类似双指针+单调队列的方式解决该问题(只是和单调队列很像)

任务安排3

有 N 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。

机器会把这 N 个任务分成若干批,每一批包含连续的若干个任务。

从时刻 0 开始,任务被分批加工,执行第 i 个任务所需的时间是 Ti。

另外,在每批任务开始前,机器需要 S 的启动时间,故执行一批任务所需的时间是启动时间 S 加上每个任务所需时间之和。

一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。

也就是说,同一批任务将在同一时刻完成。

每个任务的费用是它的完成时刻乘以一个费用系数 Ci。

请为机器规划一个分组方案,使得总费用最小。

输入格式

第一行包含两个整数 N 和 S。

接下来 N 行每行有一对整数,分别为 Ti 和 Ci,表示第 i 个任务单独完成所需的时间 Ti 及其费用系数 Ci。

输出格式

输出一个整数,表示最小总费用。

数据范围

1≤N≤3×105,
0≤S,Ci≤512,
−512≤Ti≤512

输入样例:
5 1
1 3
3 2
4 3
2 3
1 4
输出样例:
153

这道题只能用二分了

过程会爆ll记得开int128

还有注意同一条线上的多个点只能存在最边缘的两个,中间的要全删掉

举个例子 

1、2两点都符合要求,但1更好,可能会错求成2

1、2两点都行,但要选1而不能选2

但我写的二分会找到最左边的点,所以不是这里的问题,思来想去与第二题还有一点不同,就是S和T下限从1变成了0,就会出现横坐标不变的情况,出现了斜率无限大的情况,所以出现了=的情况

类似的情况会出现,造成难以估量的bug,所以,凸包一定不要留线段中间的点!!!

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'

using namespace std;

typedef pair<int, int> PII;
typedef long long ll;

const int N = 300010;

int n, S;
ll T[N], C[N];
ll f[N];
int q[N];

int main()
{
    IOS
    cin >> n >> S;
    for(int i = 1; i <= n; i ++)cin >> T[i] >> C[i];
    for(int i = 1; i <= n; i ++)
    {
        C[i] += C[i - 1];
        T[i] += T[i - 1];
    }

    int hh = 0, tt = -1;
    q[++ tt] = 0;

    for(int i = 1; i <= n; i ++)
    {
        int l = hh, r = tt;
        while(l < r)
        {
        	int mid = l + r >> 1;
			ll x1 = C[q[mid]], y1 = f[q[mid]];
			ll x2 = C[q[mid + 1]], y2 = f[q[mid + 1]];
			if(y2 - y1 >= (T[i] + S) * (x2 - x1))r = mid;
			else l = mid + 1;
		} 

        int j = q[l];
        f[i] = f[j] + T[i] * (C[i] - C[j]) + S * (C[n] - C[j]);

        ll x3 = C[i], y3 = f[i];
        while(hh < tt)
        {
            ll x1 = C[q[tt - 1]], y1 = f[q[tt - 1]];
            ll x2 = C[q[tt]], y2 = f[q[tt]];

            //注意一定是>= !!!!!!
            if((__int128)(y2 - y1) * (x3 - x1) >= (__int128)(y3 - y1) * (x2 - x1))tt --;
            else break;
        }
        q[++ tt] = i;
    }
    cout << f[n];

    return 0;
}

运输小猫

小 S 是农场主,他养了 M 只猫,雇了 P 位饲养员。

农场中有一条笔直的路,路边有 N 座山,从 1 到 N 编号。

第 i 座山与第 i−1 座山之间的距离为 Di。

饲养员都住在 1 号山。

有一天,猫出去玩。

第 i 只猫去 Hi 号山玩,玩到时刻 Ti 停止,然后在原地等饲养员来接。

饲养员们必须回收所有的猫。

每个饲养员沿着路从 1 号山走到 N 号山,把各座山上已经在等待的猫全部接走。

饲养员在路上行走需要时间,速度为 1 米/单位时间。

饲养员在每座山上接猫的时间可以忽略,可以携带的猫的数量为无穷大。

例如有两座相距为 1 的山,一只猫在 2 号山玩,玩到时刻 3 开始等待。

如果饲养员从 1 号山在时刻 2 或 3 出发,那么他可以接到猫,猫的等待时间为 0 或 1。

而如果他于时刻 1 出发,那么他将于时刻 2 经过 2 号山,不能接到当时仍在玩的猫。

你的任务是规划每个饲养员从 1 号山出发的时间,使得所有猫等待时间的总和尽量小。

饲养员出发的时间可以为负。

输入格式

第一行包含三个整数 N,M,P。

第二行包含 n−1 个整数,D2,D3,…,DN。

接下来 M 行,每行包含两个整数 Hi 和 Ti。

输出格式

输出一个整数,表示所有猫等待时间的总和的最小值。

数据范围

2≤N≤1e5,
1≤M≤1e5,
1≤P≤100,
1≤Di<1000,
1≤Hi≤N,
0≤Ti≤1e9

输入样例:
4 6 2
1 3 5
1 0
2 1
4 9
1 10
2 10
3 12
输出样例:
3

 

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'

using namespace std;

typedef pair<int, int> PII;
typedef long long ll;

const int N = 110, M = 100010;

int n, m, p;
ll f[N][M];//前i个人,收回前j只猫
ll d[M], a[M];
int q[M];
ll sum[M];

ll gety(int i, int k)
{
	return f[i - 1][k] + sum[k];
}

int main()
{
	IOS
	cin >> n >> m >> p;
	for(int i = 2; i <= n; i ++)
	{
		cin >> d[i];
		d[i] += d[i - 1];
	}
	for(int i = 1; i <= m; i ++)
	{
		int h, t;
		cin >> h >> t;
		a[i] = t - d[h];
	}
	sort(a + 1, a + 1 + m);
	for(int i = 1; i <= m; i ++)sum[i] = sum[i - 1] + a[i];
	
	memset(f, 0x3f, sizeof f);
	//排除i个人带回0只小猫的代价为0
	for(int i = 0; i <= p; i ++)f[i][0] = 0;
	//派出0个人只有可能带回0只小猫 即f[0][0] = 0;已被包含
	
	for(int i = 1; i <= p; i ++)
	{
		int hh = 0, tt = -1;
		q[++ tt] = 0;
		
		for(int j = 1; j <= m; j ++)
		{
			//先把斜率小于a[j]的去掉
			while(hh < tt && gety(i, q[hh + 1]) - gety(i, q[hh]) < a[j] * (q[hh + 1] - q[hh]))hh ++;
			
			int k = q[hh];
			f[i][j] = f[i - 1][k] - sum[j] + sum[k] + j * a[j] - k * a[j];
			
			ll x3 = j, y3 = gety(i, j);
			while(hh < tt)
			{
				ll x1 = q[tt - 1], y1 = gety(i, q[tt - 1]);
				ll x2 = q[tt], y2 = gety(i, q[tt]);
				
				if((y2 - y1) * (x3 - x1) >= (y3 - y1) * (x2 - x1))tt --;
				else break;
			}
			q[++ tt] = j;
		}
	}
	cout << f[p][m];
	
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PHP开发全新29网课交单平台源码修复全开源版本,支持聚合登陆易支付

这是一套最新版本的PHP开发的网课交单平台源代码&#xff0c;已进行全开源修复&#xff0c;支持聚合登录和易支付功能。 项目 地 址 &#xff1a; runruncode.com/php/19721.html 以下是对该套代码的主要更新和修复&#xff1a; 1. 移除了论文编辑功能。 2. 移除了强国接码…

linux之进程

一、背景 冯.诺依曼体系结构 输入设备键盘、鼠标、摄像头、话筒、磁盘、网卡...输出设备显示器、声卡、磁盘、网卡...CPU运算器、控制器存储器一般就是内存 数据在计算机的体系结构进行流动&#xff0c;流动过程中&#xff0c;进行数据的加工处理&#xff0c;从一个设备到另一…

网上兼职赚钱攻略:六种方式让你轻松上手

在互联网时代&#xff0c;网上兼职已经成为一种非常流行的赚钱方式。对于许多想要在家里挣钱的人来说&#xff0c;网上兼职不仅可以提供灵活的工作时间&#xff0c;还可以让他们在自己的兴趣领域中寻求机会&#xff0c;实现自己的财务自由。 在这里&#xff0c;我将为您介绍六…

OpenGL 实现“人像背景虚化“效果

手机上的人像模式,也被人们称作“背景虚化”或 ”双摄虚化“ 模式,也称为 Bokeh 模式,能够在保持画面中指定的人或物体清晰的同时,将其他的背景模糊掉。突出画面的主体部分,主观上美感更强烈。 人像模式的一般实现原理是,利用双摄系统获取景深信息,并通过深度传感器和图…

带流量主功能的外卖菜谱小程序源码:助你轻松领取优惠券,个人使用也可通过审查

外卖菜谱小程序源码-带流量主功能-外卖领劵个人也可过审 这套小程序优点就带很多菜谱&#xff0c;各种你爱吃菜的做法与各类食材介绍营养搭配&#xff0c;相信很多小姐姐会感兴趣。 宝妈宝爸这个小程序肯定能留的住这个群体的人脉流量&#xff0c;这是小程序最大的亮点&#…

深圳区块链交易所app系统开发,撮合交易系统开发

随着区块链技术的迅速发展和数字资产市场的蓬勃发展&#xff0c;区块链交易所成为了数字资产交易的核心场所之一。在这个快速发展的领域中&#xff0c;区块链交易所App系统的开发和撮合交易系统的建设至关重要。本文将探讨区块链交易所App系统开发及撮合交易系统的重要性&#…

【QGIS从shp文件中筛选目标区域导出为shp】

文章目录 1、写在前面2、QGIS将shp文件中目标区域输出为shp2.1、手动点选2.2、高级过滤 3、上述shp完成后&#xff0c;配合python的shp文件&#xff0c;即可凸显研究区域了 1、写在前面 利用shp文件制作研究区域mask&#xff0c;Matlab版本&#xff0c;请点击 Matlab利用shp文…

【Leetcode】单链表常见题

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;Leetcode刷题 本节内容我们来讲解常见的几道单链表的题型&#xff0c;文末会赋上单链表增删查&#xff0c;初始化等代码 目录 1.移除链表元素2.链表的中间节点3.返回倒数第K个节点&#xff1a;4.环…

【Java - 框架 - Lombok】(1) 普通Java项目通过Lombok+Logback完成日志的创建使用 - 快速上手

普通Java项目通过"Lombok""Logback"完成日志的创建使用 - 快速上手&#xff1b; 步骤A 说明 创建"Maven"项目&#xff1b; 图片 步骤B 说明 添加相关依赖项&#xff1b; 图片 代码 <!-- "Lombok"依赖项--> <dependency>&…

C语言--动态内存管理

为什么存在动态内存管理&#xff1f; 在之前我们讲到的类型创建的变量再空间开辟好之后就不能再改变了&#xff0c;但是有时候我们希望能够自由地为某个变量分配空间&#xff0c;就比如上一篇文章中的通讯录&#xff0c;在没有动态内存管理情况下&#xff0c;我们就只能为通讯…

18.字面量

文章目录 一、字面量二、区分技巧三、扩展&#xff1a; /t 制表符 一、字面量 在有些资料&#xff0c;会把字面量说成常量、字面值常量&#xff0c;这种叫法都不是很正确&#xff0c;最正确的叫法还是叫做&#xff1a;字面量。 作用&#xff1a;告诉程序员&#xff0c;数据在…

地物波谱库共享网站汇总

ENVI自5.2版本重新梳理了原有的标准波谱库&#xff0c;新增一些物质波谱&#xff0c;在ENVI5.6中存放在…\Harris\ENVI56\ resource\speclib&#xff0c;分别存放在四个文件夹中&#xff0c;储存为ENVI波谱库格式&#xff0c;有两个文件组成&#xff1a;.sli和.hdr。 ENVI保留…

小米还涉足了哪些领域

小米作为一家全球性的移动互联网企业&#xff0c;其业务领域相当广泛&#xff0c;除了核心的智能手机业务外&#xff0c;还涉足了许多其他领域。以下是对小米涉足领域的简要介绍&#xff1a; 智能硬件与IoT平台&#xff1a;小米是全球领先的智能硬件和IoT平台公司&#xff0c;致…

linux:线程同步

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》 文章目录 前言线程同步条件变量接口简单示例pthread_cond_wait为什么要有mutex伪唤醒问题的解决 (if->while) 总结 前言 本文作为我对于线程同步知识总结 线程同步 同步&…

资讯头条P3自媒体搭建

自媒体素材管理与文章管理 一.后台搭建 1.1 搭建自媒体网关 导入网关模块>>>在网关模块的pom.xml文件中添加该子模块>>>刷新maven <modules><module>heima-leadnews-app-gateway</module><!--新增--><module>heima-leadnew…

Aurora插件安装

介绍 Latext是一种基于TEX的排版系统。 CTeX中文套装是基于Windows下的MiKTeX系统&#xff0c;集成了编辑器WinEdt和PostScrip处理软件Ghostscript和GSview等主要工具。CTeX中文套装在MikTeX的基础上增加了对中文的完整支持。 CTeX&#xff1a; CTeX套装 - CTEX 下载安装 然后…

【Java程序设计】【C00345】基于Springboot的船舶监造管理系统(有论文)

基于Springboot的船舶监造管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及i…

Day50:WEB攻防-PHP应用文件包含LFIRFI伪协议编码算法无文件利用黑白盒

目录 文件包含-原理&分类&利用&修复 文件读取 文件写入 代码执行 远程利用思路 黑盒利用-VULWEB 白盒利用-CTFSHOW-伪协议玩法 78-php&http协议 79-data&http协议 80-81-日志包含 87-php://filter/write&加密编码 88-data&base64协议 …

韩顺平Java | C21网络编程

1 网络的相关概念 ip地址的组成&#xff1a;网络地址 主机地址 A类&#xff1a;0 ~ 2^7-1 0 ~ 127 B类&#xff1a;128 ~ 1282^6-1 128 ~ 191 C类&#xff1a;192 ~ 1922^5-1 192 ~ 223 D类&#xff1a;224 ~ 2242^4-1 224 ~ 239 E类&#xff1a;240 ~ 2402^3-1 240 ~ 2…

Unity PS5开发 天坑篇 之 URP管线与HDRP管线部署流程以及出包介绍04

目录 一, URP管线、HDRP管线下的Unity项目部署 1. PS5开发论坛关于Unity可支持的版本说明: 2. URP管线下的项目与部署 2.1 Build PS5 URP Project 2.2 运行画面 3. HDRP管线下的项目与部署 3.1 附上可以运行的画面: 4. PS5打包方式介绍 4.1 PC串流调试模式: Build Typ…