斜率优化dp 笔记

news2024/9/23 15:19:47

任务安排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;
}

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

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

相关文章

uniApp使用XR-Frame创建3D场景(6)播放模型动画

上篇文章讲述了如何将XR-Frame作为子组件集成到uniApp中使用 这篇我们讲解播放模型动画 先看源码 <xr-scene render-system"alpha:true" bind:ready"handleReady"> <xr-node visible"{{sec6}}"><xr-light type"ambient&qu…

火车头通过关键词采集文章的原理

随着互联网信息的爆炸式增长&#xff0c;网站管理员和内容创作者需要不断更新和发布新的文章&#xff0c;以吸引更多的用户和提升网站的排名。而火车头作为一款智能文章采集工具&#xff0c;在这一过程中发挥着重要作用。本文将探讨火车头如何通过关键词采集文章&#xff0c;以…

<QT基础(5)>事件监听

事件监听 事件监听&#xff08;Event Handling&#xff09;是在程序中监视和响应发生的事件的一种机制。在Qt中&#xff0c;事件监听是一种常见的用于处理用户输入、系统事件以及其他类型事件的方法。通过事件监听&#xff0c;您可以在发生特定事件时捕获事件并执行相应的操作…

HarmonyOS 应用开发之Want的定义与用途

Want 是一种对象&#xff0c;用于在应用组件之间传递信息。 其中&#xff0c;一种常见的使用场景是作为 startAbility() 方法的参数。例如&#xff0c;当UIAbilityA需要启动UIAbilityB并向UIAbilityB传递一些数据时&#xff0c;可以使用Want作为一个载体&#xff0c;将数据传递…

VMware vSAN OSA存储策略 - 基于虚拟机的分布式对象存储

简介 博客&#xff1a;https://songxwn.com/ 存储策略 (Storage Policy) 是管理员定义的一组规则&#xff0c;这组规则定义了数据对象在 vSAN 存储上是如何保存的&#xff0c;存储策略定义了数据存储的可靠性、访问性能等特性。vSAN 提供了基于存储策略的存储管理 SPBM (Stor…

解码“零信任”,如何带来信任感?

零信任的“信任”来源&#xff0c;并非凭空而生&#xff0c;而是建立在严格、细致且持续的验证、策略之上。它不仅能够提升企业的安全防护能力&#xff0c;也在加速安全技术的创新与演进。 推动创新 零信任理念激活网络安全 身份和访问管理革新。零信任理念“永不信任&#…

Jenkins升级中的小问题

文章目录 使用固定版本安装根据jenkins页面下载war包升级jenkins重启jenkins报错问题解决 K8s部署过程中的一些小问题 ##### Jenkins版本小插曲 ​ 在Jenkins环境进行插件安装时全部清一色飘红&#xff0c;发现是因为Jenkins版本过低导致&#xff0c;报错的位置可以找到更新je…

【InternLM 实战营第二期笔记】书生·浦语大模型全链路开源体系及InternLM2技术报告笔记

大模型 大模型成为发展通用人工智能的重要途径 专用模型&#xff1a;针对特定任务&#xff0c;一个模型解决一个问题 通用大模型&#xff1a;一个模型应对多种任务、多种模态 书生浦语大模型开源历程 2023.6.7&#xff1a;InternLM千亿参数语言大模型发布 2023.7.6&#…

【React】onClick点击事件传参的4种方式

记录React onClick 点击事件传参的 4 种方式 方式一&#xff1a;使用内联箭头函数 import React, { MouseEvent } from "react";function App() {const handleClick (event: MouseEvent<HTMLButtonElement>, name: string) > {console.log(event)console.…

Unity图集编辑器

图集编辑器 欢迎使用图集编辑器新的改变编辑器图片 欢迎使用图集编辑器 Unity图集操作很是费劲 无法批量删除和添加图集中的图片 新的改变 自己写了一个图集编辑器 客&#xff1a; 支持批量删除 左键点击图片代表选中 右键点击图标定位到资产支持批量添加 选中图片拖拽到编…

小程序利用WebService跟asp.net交互过程发现的问题并处理

最近在研究一个项目&#xff0c;用到asp.net跟小程序交互&#xff0c;简单的说就是小程序端利用wx.request发起请求。获取asp.net 响应回来的数据。但经常会报错。点击下图的测试按钮 出现如下错误&#xff1a; 百思不得其解&#xff0c;试了若干方法&#xff0c;都不行。 因为…

非wpf应用程序项目【类库、用户控件库】中使用HandyControl

文章速览 前言参考文章实现方法1、添加HandyControl包&#xff1b;2、添加资源字典3、修改资源字典内容 坚持记录实属不易&#xff0c;希望友善多金的码友能够随手点一个赞。 共同创建氛围更加良好的开发者社区&#xff01; 谢谢~ 前言 wpf应用程序中&#xff0c;在入口项目中…

单例模式如何保证实例的唯一性

前言 什么是单例模式 指一个类只有一个实例&#xff0c;且该类能自行创建这个实例的一种创建型设计模式。使用目的&#xff1a;确保在整个系统中只能出现类的一个实例&#xff0c;即一个类只有一个对象。对于频繁使用的对象&#xff0c;“忽略”创建时的开销。特点&#xff1a…

arp 协议

数据链路层 我们之前学习到的 IP 协议解决的是数据跨网络传输的问题。 数据链路层解决的是&#xff1a;直接相连的主机&#xff0c;进行数据交付的问题&#xff01; 直接相连的设备包括我们的电脑&#xff0c;路由器等等哈&#xff01; 我们在网络基础那篇文章中讲过什么是以…

Unity | 射线检测及EventSystem总结

目录 一、知识概述 1.Input.mousePosition 2.Camera.ScreenToWorldPoint 3.Camera.ScreenPointToRay 4.Physics2D.Raycast 二、射线相关 1.3D&#xff08;包括UI&#xff09;、射线与ScreenPointToRay 2.3D&#xff08;包括UI&#xff09;、射线与ScreenToWorldPoint …

基于单片机锂电池电量检测数码管显示系统设计

**单片机设计介绍&#xff0c;基于单片机锂电池电量检测数码管显示系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机锂电池电量检测数码管显示系统设计的主要目标是实时、准确地检测锂电池的电量&#xff0c;并…

如何利用webpack来优化前端性能

当涉及前端性能优化时&#xff0c;Webpack 是一款不可或缺的工具。它不仅仅是一个模块打包工具&#xff0c;还提供了各种功能和插件&#xff0c;可以帮助开发人员优化前端应用程序的性能。在这篇文章中&#xff0c;我们将深入探讨如何有效地利用 Webpack 来优化前端性能&#x…

「15」色源:添加指定色彩的纯色画面素材

「15」色源添加指定色彩的纯色画面素材 在OBS软件里&#xff0c;在来源里可以增加色源&#xff0c;添加一个色块到您的场景中&#xff0c;作为一个背景色或辅助色。 图中的显示器就是加了色源的 实操步骤 第1步 添加色源 在「来源」的左下角&#xff0c;点「」选择「色源」&a…

使用Kaggle API快速下载Kaggle数据集

前言 在使用Kaggle网站下载数据集时&#xff0c;直接在网页上点击下载可能会很慢&#xff0c;甚至会出现下载失败的情况。本文将介绍如何使用Kaggle API快速下载数据集。 具体步骤 安装Kaggle API包 在终端中输入以下命令来安装Kaggle API相关的包&#xff1a; pip install…

「DevExpress中文教程」如何将DevExtreme JS HTML编辑器集成到WinForms应用

在本文中我们将演示一个混合实现&#xff1a;如何将web UI工具集成到WinForms桌面应用程序中。具体来说&#xff0c;我们将把DevExtreme JavaScript WYSIWYG HTML编辑器(作为DevExtreme UI组件套件的一部分发布的组件)集成到Windows Forms应用程序中。 获取DevExtreme v23.2正式…