信息学奥赛一本通 1606:【 例 1】任务安排 1 | 洛谷 P2365 任务安排

news2025/2/1 2:55:44

【题目链接】

ybt 1606:【 例 1】任务安排 1
洛谷 P2365 任务安排

【题目考点】

1. 动态规划:线性动规

【解题思路】

可以先了解法1,虽然不是正解,但该解法只使用了动规的基本思路,易于理解,有助于理解这一问题。而后再了解该题的正解解法2。

解法1(非正解): 二维状态, O ( n 3 ) O(n^3) O(n3)解法

第i个任务执行时间为 t i t_i ti,第i个任务的费用系数为为 c i c_i ci
记序列t的前缀和为T,序列c的前缀和为C
抽象问题,可知:每个任务是一个元素,构成一个序列。一批任务就是序列的一个子段。划分批次的方案,就是对一个序列划分为多个子段的方案。

1. 确定状态:
  • 阶段:前i个元素,分成j个子段
  • 决策:一个元素被分到哪一个子段
  • 策略:子段划分方案
  • 策略集合:前i个元素分成j个子段的所有子段划分方案
  • 条件:费用最小
  • 统计量:费用

状态定义 d p i , j dp_{i,j} dpi,j:前i个元素分成j个子段的所有子段划分方案中,费用最小的方案的费用。

  • 初始状态: d p i , 1 dp_{i,1} dpi,1:前i个元素分成1个子段的最小费用为 ( s + T i ) ⋅ C i (s+T_i)\cdot C_i (s+Ti)Ci
    结合后面的状态转移方程,该初始状态等价于先将dp数组设为无穷大,而后将 d p 0 , 0 dp_{0,0} dp0,0设为0
2. 确定状态转移方程

策略集合:前i个元素分成j个子段的所有子段划分方案
分割策略集合:根据第j个子段的起始下标分割策略集合
设前j-1个子段包含序列下标1~k的元素。第j个子段的起始下标为k+1。
可知k的范围为 j ≤ k < i j\le k<i jk<i

当前面j-1个子段每个子段只有一个数字时,k最小,为j。
当第j个子段只有一个数字时,k最大,为i-1。

当第j子段的起始下标为k+1时,前k个数字分成j-1个子段的最小费用,再加上第j个子段的费用,就是当前子段划分下的最小费用。

第1到第i任务一共有j个子段(批次),开机启动耗时 s ⋅ j s\cdot j sj。第1个任务到第i任务耗费总时间为 T [ i ] T[i] T[i],因此这批任务的完成时刻是 s ⋅ j + T i s\cdot j+T_i sj+Ti
第k+1个任务的费用为 ( s ⋅ j + T i ) ⋅ c k + 1 (s\cdot j+T_i)\cdot c_{k+1} (sj+Ti)ck+1
第k+2个任务的费用为 ( s ⋅ j + T i ) ⋅ c k + 2 (s\cdot j+T_i)\cdot c_{k+2} (sj+Ti)ck+2

第i个任务的费用为 ( s ⋅ j + T i ) ⋅ c i (s\cdot j+T_i)\cdot c_{i} (sj+Ti)ci
因此总费用加和为 ( s ⋅ j + T i ) ⋅ ( C i − C k ) (s\cdot j+T_i)\cdot (C_i-C_k) (sj+Ti)(CiCk)
因此状态转移方程为:
d p i , j = m i n { d p k − 1 , j − 1 + ( s ⋅ j + T i ) ⋅ ( C i − C k ) } , j ≤ k < i dp_{i,j} = min\{dp_{k-1,j-1}+(s\cdot j+T_i)\cdot (C_i-C_k)\}, j\le k<i dpi,j=min{dpk1,j1+(sj+Ti)(CiCk)},jk<i

该解法的时间复杂度是 O ( n 3 ) O(n^3) O(n3)
在洛谷上是70分,一本通上是60分。
有测试点超时,因为n是5000, O ( n 3 ) O(n^3) O(n3)必然会超时。
有测试点是答案错误,因为结果会超过int的范围,需要使用long long类型表示。而如果开long long dp[5005][5005],又会空间超限。所以开int dp[5005][5005],有些测试点的结果由于超出int的范围而产生答案错误。

解法2(正解): 一维状态, O ( n 2 ) O(n^2) O(n2)解法

上一解法在确定状态转移方程时是这样做的:
当第j子段的起始下标为k+1时,前k个数字分成j-1个子段的最小费用,再加上第j个子段的费用,就是当前子段划分下的最小费用。
第j个子段也就是前i个元素进行划分子段所得到的最后一个子段。最后一个子段确定后,第1~k元素自然需要选择费用最少的子段划分方案,无论分成多少子段。
因此我们可以把状态定义中”分成j个子段“这一维度去掉。
d p [ i ] dp[i] dp[i]的意义为:前i个元素进行子段划分的所有方案中,费用最少的方案的费用。
如果这样进行状态定义,我们就无法得知前i个元素分成了几个子段,那么最后一个子段任务的完成时间 s ⋅ j + T i s\cdot j+T_i sj+Ti中的子段数量j就是未知的。
这里可以将开机时间产生的费用和任务时间产生的费用分别考虑。
仍然设最后一个子段第一个元素的下标为k+1,那么 0 ≤ k < i 0\le k < i 0k<i

当1~i整个序列就是最后一个子段,此时k最小为0
当最后一个子段只有一个第i元素,次数k最大为i-1

如果完成时刻只考虑任务耗费时间,那么最后一个子段任务的完成时间为 T [ i ] T[i] T[i]
最后一个子段的任务的费用分别是:
第k+1个任务的费用为 T i ⋅ c k + 1 T_i\cdot c_{k+1} Tick+1
第k+2个任务的费用为 T i ⋅ c k + 2 T_i\cdot c_{k+2} Tick+2

第i个任务的费用为 T i ⋅ c i T_i\cdot c_i Tici
总费用为 T i ⋅ ( C i − C k ) T_i\cdot (C_i-C_k) Ti(CiCk)
然后考虑开机时间,当前最后一批任务(子段)的开机时间为s,由于这一次开机影响到的任务(元素)为第k+1任务到第n任务,这些任务的完成时间由于这一次开机延后了时间s,
产生的费用为 s ⋅ c k + 1 + s ⋅ c k + 2 + . . . + s ⋅ c n s\cdot c_{k+1}+s\cdot c_{k+2}+...+s\cdot c_{n} sck+1+sck+2+...+scn
= s ⋅ ( C n − C k ) =s\cdot (C_n-C_k) =s(CnCk)
我们把开机对后面所有任务产生的费用和完成任务的费用加在一起,作为状态定义。这是一种费用提前计算思想
该方法最终的状态定义为:
d p i dp_i dpi:前i个任务的所有子段划分方案中,执行任务的费用 加上当前方案下每批任务的启动时间对后续任务产生的费用加和 最小的划分方案的费用。
该状态定义与之前的状态定义(前i个元素进行子段划分的所有方案中,费用最少的方案的费用)不同,但该问题最终求的是 d p n dp_n dpn,两种定义下 d p n dp_n dpn的值一定是相同的。
根据上述分析,可知状态转移方程为:
d p i = m i n { d p k + T i ⋅ ( C i − C k ) + s ⋅ ( C n − C k ) } , 0 ≤ k < i dp_i = min\{dp_k+T_i\cdot (C_i-C_k)+s\cdot (C_n-C_k)\}, 0\le k< i dpi=min{dpk+Ti(CiCk)+s(CnCk)},0k<i
该解法下变量j没有用到,个人习惯能用j就不用k。可以将符号k替换为符号j,状态转移方程为:
d p i = m i n { d p j + T i ⋅ ( C i − C j ) + s ⋅ ( C n − C j ) } , 0 ≤ j < i dp_i = min\{dp_j+T_i\cdot (C_i-C_j)+s\cdot (C_n-C_j)\}, 0\le j< i dpi=min{dpj+Ti(CiCj)+s(CnCj)},0j<i
该解法时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( n ) O(n) O(n),可以通过此题。

【注】本题可以进一步通过斜率优化使得时间复杂度降至 O ( n ) O(n) O(n),该方法见[洛谷 P10979 任务安排 2]

【题解代码】

解法1(非正解): 二维状态, O ( n 3 ) O(n^3) O(n3)解法 (洛谷70分 一本通60分)

#include<bits/stdc++.h>
using namespace std;
#define N 5005
int n, s, t[N], c[N], T[N], C[N], dp[N][N], ans = 1e9;//dp[i][j]:前i个数字分成j个子段的所有方案中,费用最小的方案的费用
int main()
{
 	cin >> n >> s;
 	for(int i = 1; i <= n; ++i)
 	{
	 	cin >> t[i] >> c[i];
 		T[i] = T[i-1]+t[i];
		C[i] = C[i-1]+c[i];
	}
	memset(dp, 0x3f, sizeof(dp));
	dp[0][0] = 0;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= i; ++j)
			for(int k = j; k <= i; ++k)
				dp[i][j] = min(dp[i][j], dp[k-1][j-1]+(s*j+T[i])*(C[i]-C[k-1]));
	for(int j = 1; j <= n; ++j)
		ans = min(ans, dp[n][j]);
	cout << ans;
	return 0;
}

解法2(正解): 一维状态, O ( n 2 ) O(n^2) O(n2)解法

#include<bits/stdc++.h>
using namespace std;
#define N 5005
long long n, s, t[N], c[N], T[N], C[N], ans = 1e18, dp[N];//dp[i]:前i个任务的所有子段划分方案中,执行任务的费用 加上当前方案下每批任务的启动时间对后续任务产生的费用加和 最小的划分方案的费用
int main()
{
 	cin >> n >> s;
 	for(int i = 1; i <= n; ++i)
 	{
	 	cin >> t[i] >> c[i];
 		T[i] = T[i-1]+t[i];
		C[i] = C[i-1]+c[i];
	}
	memset(dp, 0x3f, sizeof(dp));
	dp[0] = 0;
	for(int i = 1; i <= n; ++i)
		for(int j = 0; j <= i; ++j)
			dp[i] = min(dp[i], dp[j]+T[i]*(C[i]-C[j])+s*(C[n]-C[j]));
	cout << dp[n];
	return 0;
}

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

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

相关文章

Linux Samba 低版本漏洞(远程控制)复现与剖析

目录 前言 漏洞介绍 漏洞原理 产生条件 漏洞影响 防御措施 复现过程 结语 前言 在网络安全的复杂生态中&#xff0c;系统漏洞的探索与防范始终是保障数字世界安全稳定运行的关键所在。Linux Samba 作为一款在网络共享服务领域应用极为广泛的软件&#xff0c;其低版本中…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.27 线性代数王国:矩阵分解实战指南

1.27 线性代数王国&#xff1a;矩阵分解实战指南 #mermaid-svg-JWrp2JAP9qkdS2A7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JWrp2JAP9qkdS2A7 .error-icon{fill:#552222;}#mermaid-svg-JWrp2JAP9qkdS2A7 .erro…

初二回娘家

昨天下午在相亲相爱一家人群里聊天&#xff0c;今天来娘家拜年。 聊天结束后&#xff0c;开始准备今天的菜肴&#xff0c;梳理了一下&#xff0c;凉菜&#xff0c;热菜&#xff0c;碗菜。 上次做菜&#xff0c;粉丝感觉泡的不透&#xff0c;有的硬&#xff0c;这次使用开水浸泡…

【Block总结】PKI 模块,无膨胀多尺度卷积,增强特征提取的能力|即插即用

论文信息 标题: Poly Kernel Inception Network for Remote Sensing Detection 作者: Xinhao Cai, Qiuxia Lai, Yuwei Wang, Wenguan Wang, Zeren Sun, Yazhou Yao 论文链接&#xff1a;https://arxiv.org/pdf/2403.06258 代码链接&#xff1a;https://github.com/NUST-Mac…

Blazor-@bind

数据绑定 带有 value属性的标记都可以使用bind 绑定&#xff0c;<div>、<span>等非输入标记&#xff0c;无法使用bind 指令的&#xff0c;默认绑定了 onchange 事件&#xff0c;onchange 事件是指在输入框中输入内容之后&#xff0c;当失去焦点时执行。 page &qu…

架构技能(六):软件设计(下)

我们知道&#xff0c;软件设计包括软件的整体架构设计和模块的详细设计。 在上一篇文章&#xff08;见 《架构技能&#xff08;五&#xff09;&#xff1a;软件设计&#xff08;上&#xff09;》&#xff09;谈了软件的整体架构设计&#xff0c;今天聊一下模块的详细设计。 模…

C++并发编程指南07

文章目录 [TOC]5.1 内存模型5.1.1 对象和内存位置图5.1 分解一个 struct&#xff0c;展示不同对象的内存位置 5.1.2 对象、内存位置和并发5.1.3 修改顺序示例代码 5.2 原子操作和原子类型5.2.1 标准原子类型标准库中的原子类型特殊的原子类型备选名称内存顺序参数 5.2.2 std::a…

MySQL 容器已经停止(但仍然存在),但希望重新启动它,并使它的 3306 端口映射到宿主机的 3306 端口是不可行的

重新启动容器并映射端口是不行的 由于你已经有一个名为 mysql-container 的 MySQL 容器&#xff0c;你可以使用 docker start 启动它。想要让3306 端口映射到宿主机是不行的&#xff0c;实际上&#xff0c;端口映射是在容器启动时指定的。你无法在容器已经创建的情况下直接修改…

春晚舞台上的人形机器人:科技与文化的奇妙融合

文章目录 人形机器人Unitree H1的“硬核”实力传统文化与现代科技的创新融合网友热议与文化共鸣未来展望&#xff1a;科技与文化的更多可能结语 2025 年央视春晚的舞台&#xff0c;无疑是全球华人目光聚焦的焦点。就在这个盛大的舞台上&#xff0c;一场名为《秧BOT》的创意融合…

将pandas.core.series.Series类型的小数转化成百分数

大年初二&#xff0c;大家过年好&#xff0c;蛇年行大运&#xff01; 今天在编写一个代码的时候&#xff0c;使用 import pandas as pd产生了pandas.core.series.Series类型的数据&#xff0c;里面有小数&#xff0c;样式如下&#xff1a; 目的&#xff1a;将这些小数转化为百…

详细解释java当中的所有知识点(前言及数据类型及变量)(第一部分)

会将java当中的所有的知识点以及相关的题目进行分享&#xff0c;这是其中的第一部分&#xff0c;用红色字体标注出重点&#xff0c;以及加粗的方式进行提醒 目录 一、Java语言概述 1.Java语言简介 2.语言优势 二、main方法 1.Java程序结构组成 2.运行Java程序 3.注释 4.…

字节iOS面试经验分享:HTTP与网络编程

字节iOS面试经验分享&#xff1a;HTTP与网络编程 &#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 目录 字节iOS面试经验分享&#xff1a;HTT…

代码随想录_栈与队列

栈与队列 232.用栈实现队列 232. 用栈实现队列 使用栈实现队列的下列操作&#xff1a; push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。 思路: 定义两个栈: 入队栈, 出队栈, 控制出入…

【Oracle篇】使用Hint对优化器的执行计划进行干预(含单表、多表、查询块、声明四大类Hint干预)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;从事IT领域✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对SQLserver、NoSQL(…

论文阅读(九):通过概率图模型建立连锁不平衡模型和进行关联研究:最新进展访问之旅

1.论文链接&#xff1a;Modeling Linkage Disequilibrium and Performing Association Studies through Probabilistic Graphical Models: a Visiting Tour of Recent Advances 摘要&#xff1a; 本章对概率图模型&#xff08;PGMs&#xff09;的最新进展进行了深入的回顾&…

【Matlab高端绘图SCI绘图模板】第006期 对比绘柱状图 (只需替换数据)

1. 简介 柱状图作为科研论文中常用的实验结果对比图&#xff0c;本文采用了3组实验对比的效果展示图&#xff0c;代码已调试好&#xff0c;只需替换数据即可生成相关柱状图&#xff0c;为科研加分。通过获得Nature配色的柱状图&#xff0c;让你的论文看起来档次更高&#xff0…

YOLOv8源码修改(4)- 实现YOLOv8模型剪枝(任意YOLO模型的简单剪枝)

目录 前言 1. 需修改的源码文件 1.1添加C2f_v2模块 1.2 修改模型读取方式 1.3 增加 L1 正则约束化训练 1.4 在tensorboard上增加BN层权重和偏置参数分布的可视化 1.5 增加剪枝处理文件 2. 工程目录结构 3. 源码文件修改 3.1 添加C2f_v2模块和模型读取 3.2 添加L1正则…

后端token校验流程

获取用户信息 前端中只有 await userStore.getInfo() 表示从后端获取数据 在页面中找到info对应的url地址&#xff0c;在IDEA中查找 这里是getInfo函数的声明&#xff0c;我们要找到这个函数的使用&#xff0c;所以点getInfo() Override public JSONObject getInfo() {JSO…

Ansible自动化运维实战--通过role远程部署nginx并配置(8/8)

文章目录 1、准备工作2、创建角色结构3、编写任务4、准备配置文件&#xff08;金甲模板&#xff09;5、编写变量6、编写处理程序7、编写剧本8、执行剧本Playbook9、验证-游览器访问每台主机的nginx页面 在 Ansible 中&#xff0c;使用角色&#xff08;Role&#xff09;来远程部…

C语言自定义数据类型详解(二)——结构体类型(下)

书接上回&#xff0c;前面我们已经给大家介绍了如何去声明和创建一个结构体&#xff0c;如何初始化结构体变量等这些关于结构体的基础知识。下面我们将继续给大家介绍和结构体有关的知识&#xff1a; 今天的主题是&#xff1a;结构体大小的计算并简单了解一下位段的相关知识。…