首页 > 其他分享 >斜率优化入门 任务分配

斜率优化入门 任务分配

时间:2023-11-26 15:36:11浏览次数:33  
标签:入门 这题 任务分配 决策 斜率 任务 优化 单调

终于开始斜率优化了。。
洛谷P2365 任务安排

题目描述

nn 个任务排成一个序列在一台机器上等待完成(顺序不得改变),这 nn 个任务被分成若干批,每批包含相邻的若干任务。

从零时刻开始,这些任务被分批加工,第 ii 个任务单独完成所需的时间为 titi​。在每批任务开始前,机器需要启动时间 ss,而完成这批任务所需的时间是各个任务需要时间的总和(同一批任务将在同一时刻完成)。

每个任务的费用是它的完成时刻乘以一个费用系数 fifi​。请确定一个分组方案,使得总费用最小。

输入格式

第一行一个正整数 nn。
第二行是一个整数 ss。

下面 nn 行每行有一对数,分别为 titi​ 和 fifi​,表示第 ii 个任务单独完成所需的时间是 titi​ 及其费用系数 fifi​。

输出格式

一个数,最小的总费用。

输入输出样例

输入 #1
5
1
1 3
3 2
4 3
2 3
1 4
输出 #1
153

说明/提示

【数据范围】
对于 100%100% 的数据,1≤n≤50001≤n≤5000,0≤s≤500≤s≤50,1≤ti,fi≤1001≤ti​,fi​≤100。

【样例解释】
如果分组方案是 {1,2},{3},{4,5}{1,2},{3},{4,5},则完成时间分别为 {5,5,10,14,14}{5,5,10,14,14},费用 C=15+10+30+42+56C=15+10+30+42+56,总费用就是 153153。

 

朴素方程很简单,f[i][j]表示把前i个任务分为j组的时候的最小代价
转移显然
这题要求O(n^2),这种转移是O(n^3),不能通过
这边还是把方程写出来了


额,j只和j-1有关,可以优化一维的空间
但是这边没什么必要
考虑优化
有j*SumW[i]这一项,无法单调队列优化
考虑我们要j这一维度的作用,是为了统计S来消除分组带来的后效性
但是仔细考虑,发现这个后效性是可统计的,也就是可以消除
我们每一次分组,增加了S的时间,只需要加上这个S导致的增加的代价即可
所以j这一维可以优化

状态设计变为:
f[i]表示把前i个任务分为了若干组时,算上罚时导致后面的分组代价增加后最小的代价为多少

 转移方程变为

 

 时间复杂度变为了O(n^2)

这是一个很重要的方法,通过提前统计所有可统计的后效性来优化dp
使用条件还是挺苛刻的,要求一个维度所代表的后效性可统计
多注意一下就好了,算是提供了一种新的优化思路

但是这题时一道斜率优化例题。。
O(n^2)并不是极限
额,方程变个形

 假设k是我们的最优决策点,所以不用管ma
(可以去luogu看这题的题解,讲的很好
我们只需要维护一个决策点的下凸壳,这样里面放的决策点就都是最优决策的候选项
注意开longlong
斜率优化尽量写成相乘的模式,相除容易导致精度的损失而决策错误
因为相乘的原因,所以容易需要开longlong,要注意
正常的情况下,这个队列里面的决策是都需要保留的,但是这题的斜率比较特殊,是SumT[i]+S,显然,随着i的增加,它是单调递增的,所以前面的决策可以直接出队排除
如果不是单调递增的,那么就需要用二分查找来在这个队列里面logn找到需要的决策
还是非常快的

斜率优化。。几乎已经是线性dp的极限了吧?
在求最优解的dp中,结合上线性规划和单调队列的斜率优化,真的是。。
很难理解,也很神奇
使用条件和单调队列有些相似,决策区间单调移动,但是转移方程的形式更加的没有限制,单调队列优化更像是斜率优化的特殊情况

既然i和j的乘积现在也能够考虑了,那,如果是i*i*j或者类似的形式?
i的次方在斜率的部分,这个倒是直接计算就ok,如果是j的次方好像也没什么问题啊
主要是f[j]不太能有次方?假如两边开根号,仿射变换后的坐标系直线会变成斜线,斜率优化就不可能可以用了。。因为线性规划在这样的坐标系里面废掉了
那如果我不开次方,留着呢?
好像可以啊
f[i]在截距里面其实没什么变化,一样转移啊
可以的

这题的代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
    char c=getchar();int a=0,b=1;
    for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
    for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
ll n,S,SumT[5001],SumW[5001],f[5001],q[5001];
int main()
{
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    n=read();S=read();
    for(int i=1;i<=n;i++)
    {
        SumT[i]=SumT[i-1]+read();
        SumW[i]=SumW[i-1]+read();
    }
    memset(f,0x3f,sizeof(f));
    f[0]=0;
    int l=1,r=1;
    for(int i=1;i<=n;i++)
    {
        while(l<r&&(f[q[l+1]]-f[q[l]])<=(S+SumT[i])*(SumW[q[l+1]]-SumW[q[l]]))l++;
        f[i]=f[q[l]]+SumT[i]*(SumW[i]-SumW[q[l]])+S*(SumW[n]-SumW[q[l]]);
        while(l<r&& (f[i]-f[q[r]])*(SumW[q[r]]-SumW[q[r-1]]) <= (f[q[r]]-f[q[r-1]])*(SumW[i]-SumW[q[r]]) )r--;
        q[++r]=i;
    }
    cout<<f[n]<<endl;
    return 0;
}

 

标签:入门,这题,任务分配,决策,斜率,任务,优化,单调
From: https://www.cnblogs.com/HLZZPawa/p/17856064.html

相关文章

  • Flutter的动画开发入门简介
    Flutter动画库中的核心类,插入用于指导动画的值。Animation对象知道动画目前的状态(例如,是否开始,暂停,前进或倒退),但是对屏幕上显示的内容一无所知。AnimationController管理Animation。CurvedAnimation定义进程为非线性曲线。Tween为动画对象插入一个范围值。例如,Tween可......
  • 小白指针(七)--------新手入门
    我们之前讲了很多。但是指针的路还需要继续往下走,其实也快结束了,学习就是一种坚持的路,只有往前走才能学到更多,看到更多。(。・ω・。),今天的可能比前面的多,请耐心学习,谢谢在指针更新完之后我会将指针的内容,整理发一片这里是指针的快结束了,这里的一节结束还有最后有一片文章了,朋友们加油呀!一......
  • C#入门实践
    ①必备知识点_控制台相关staticvoidMain(string[]args){Console.WriteLine("控制台相关");#region知识点一复习输入输出//输出//Console.WriteLine("123123");//光标空行//Console.Write("1......
  • FreeRTOS入门教程(任务通知)
    (文章目录)前言本篇文章将带大家学习任务通知的概念和使用方法。一、什么是任务通知FreeRTOS中的任务通知(TaskNotification)是一种轻量级的同步机制,允许一个任务通知另一个任务已发生的事件或条件。这对于多任务系统中的协作和同步非常有用。以下是有关FreeRTOS任务通知的详细......
  • dp入门 cf189A
    题意:有一个长为n的带子,可以将它剪为a,b,c三种长度,问最多能剪多少段?分析:是一道与完全背包类似的题,但这里要求的是背包正好装满。该怎么解决这一问题?我们可以将f数组全部初始化为-1,状态转移时如果上一个状态不是-1才可以转移。状态转移方程\(f_{i,j}\)表示前i个物品恰好装满j的......
  • DataX快速入门
    DataX3.0快速入门一、DataX3.0概览DataX是阿里云DataWorks数据集成的开源版本,在阿里巴巴集团内部被广泛使用的离线数据同步工具/平台。解决了数据库之中的数据同步、迁移问题,把网状结构转为星型结构,主要用于数据库之间传送业务数据。为了解决异构数据源同步问题,DataX将复杂的......
  • XSS基本入门
    xss简单介绍xss概念跨站脚本攻击(CrossSiteScripting),为不和层叠样式表(CascadingStyleSheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户目的。xss危......
  • kafka入门(二): 位移提交
    位移提交:Kafka的每条消息都有唯一的offset,用来表示消息在分区中对应的位置。有的也称之为"偏移量"。消费者每次在poll()拉取消息,它要返回的是还没有消费过的消息集,因此,需要记录上一次消费时的消费位移,并且持久化。消费者在消费完消息之后,需要执行消费位移的提交。自动位......
  • 工具 | Vshell使用入门
    写在前面   "Vshell是一款go编写的主机群管理工具(RAT)"。    发现Vshell作者团队非常低调,项目Github上Readme介绍非常简短,网上也很少有使用介绍。写个基础入门,记录从配置到主机管理、搭建隧道。本文仅作为工具介绍,请勿用于任何违法场景。    未经授权请勿利用文章......
  • Java零基础入门-数组
    Java零基础入门-数组前言Java是一门面向对象的编程语言,被广泛应用于各个领域。数组是Java编程中最基本也是最重要的数据结构之一,它可以用来存储一组数据,并且方便进行操作和处理。本文将为大家介绍Java数组的基本概念、语法和常见应用场景,帮助初学者快速入门。摘要本文将从以下......