题目描述

一个歌手准备从A城去B城参加演出。

  1. 按照合同,他必须在 T 天内赶到
  2. 歌手途经 N 座城市
  3. 歌手不能往回走
  4. 每两座城市之间需要的天数都可以提前获知。
  5. 歌手在每座城市都可以在路边卖唱赚钱。
    经过调研,歌手提前获知了每座城市卖唱的收入预期: 如果在一座城市第一天卖唱可以赚M,后续每天的收入会减少D(第二天赚的钱是 M - D,第三天是 M - 2D …)。如果收入减少到 0 就不会再少了。
  6. 歌手到达后的第二天才能开始卖唱。如果今天卖过唱,第二天才能出发。
    贪心的歌手最多可以赚多少钱

输入描述
第一行两个数字 T 和 N,中间用空格隔开。

  • T 代表总天数,0 < T < 1000
  • N 代表路上经过 N 座城市,0 < N < 100

第二行 N+1 个数字,中间用空格隔开。代表每两座城市之间耗费的时间。

  • 其总和 ≤ T。

接下来 N 行,每行两个数字 M 和 D,中间用空格隔开。代表每个城市的收入预期。

  • 0 < M < 1000
  • 0 < D < 100

用例
输入

10 2
1 1 2
120 20
90 10

输出

540

说明
总共10天,路上经过2座城市。
路上共花 1+1+2=4 天
剩余6天最好的计划是在第一座城市待3天,在第二座城市待3天。
在第一座城市赚的钱:120 + 100 + 80 = 300
在第二座城市赚的钱:90 + 80 + 70 = 240
一共 300 + 240 = 540。

思考

先计算除去路上花费的天数后剩余可分配天数,在 N 个城市中按顺序卖唱的最大收益。用例中的数据,城市1的日收益如下:
120 100 80 60 40 20,城市2 的日收益: 90 80 70 60 50 40,假如剩余天数是6天,都在第一座城市卖唱,那么收益数组为:
[120,100,80,60,40,20],显然后3天的收益 [60,40,20] 小于第二座城市前3天的收益 [90,80,70],那么最大收益就是第一座城市停留3天收益+第二座城市停留3天的收益,即[120,100,80,90,80,70]。具体算法应该是先按顺序遍历每座经过的城市,对每个城市,假设剩余天数都停留在这座城市,得到一个收益列表 profits;下一轮循环遍历下一座城市时重复之前操作,但把收益列表中最小的收益数替换为当前更大的收益,这样最终的收益列表profits尽可能包含了每座城市中最大的收益数,即是整个歌手能获得的最大卖唱收益。可以用优先队列快速获取最小收益,并将较大收益数入队,优化时间复杂度。有些编程语言没有内置优先队列,不熟悉实现起来比较耗费时间,比如JavaScript,可以用数组模拟下,如:let minIndex = queue.lastIndexOf(Math.min(...queue)), queue[minIndex] = curElem;,只要做题时能通过就行。

算法过程

该算法基于最小优先队列(Min-Heap) 实现,核心思路是:从所有城市的可能卖唱日收益中,筛选出最大的leftDays个收益(leftDays为可用于卖唱的剩余天数),总和即为最大总收益。具体步骤如下:

步骤1:计算可用于卖唱的剩余天数
  • 首先计算总路程耗时:将输入的N+1段路程时间求和(记为totalRoadDays)。
  • 剩余可卖唱天数为:leftDays = T - totalRoadDays。若leftDays ≤ 0,则无时间卖唱,直接返回0。
步骤2:初始化最小优先队列
  • 使用最小优先队列(堆)存储当前筛选出的最大日收益,队列最多容纳leftDays个元素(因为总共有leftDays天可卖唱)。
  • 最小优先队列的特性是:顶部元素始终是当前队列中最小的元素,便于快速替换为更大的收益。
步骤3:遍历所有城市,计算并筛选日收益

对于每座城市,按顺序计算在该城市停留第1天、第2天……直到第leftDays天的日收益(超过leftDays天的收益无需计算,因为总天数有限),并按规则加入队列:

  • 日收益计算规则:第j天(j从1开始)的收益为 max(M - D*(j-1), 0)M为初始收益,D为每日递减值,收益不能为负)。
  • 队列操作规则
    • 若队列元素数量 < leftDays:直接将当前日收益加入队列(此时需要填充所有可能的天数)。
    • 若队列已满(元素数量 = leftDays):比较当前日收益与队列顶部的最小收益。若当前收益更大,则移除队列中最小的收益,将当前收益加入队列(保证队列始终保留目前最大的leftDays个收益)。
步骤4:计算最大总收益

当所有城市的所有可能日收益都处理完毕后,队列中存储的是最大的leftDays个日收益。将这些收益求和,即为歌手能获得的最大总收益。

示例验证(对应题目用例)

  1. 计算剩余天数:总天数T=10,路程时间1+1+2=4,故leftDays=6
  2. 处理第一座城市(M=120,D=20)
    • 日收益依次为:120(第1天)、100(第2天)、80(第3天)、60(第4天)、40(第5天)、20(第6天)。
    • 队列初始为空,依次加入这6个收益,队列元素为[20,40,80,60,100,120](堆顶为最小元素20)。
  3. 处理第二座城市(M=90,D=10)
    • 日收益依次为:90(第1天)、80(第2天)、70(第3天)、60(第4天)、50(第5天)、40(第6天)。
    • 逐个处理:
      • 90 > 堆顶20 → 移除20,加入90 → 队列元素更新(堆顶40)。
      • 80 > 堆顶40 → 移除40,加入80 → 队列元素更新(堆顶60)。
      • 70 > 堆顶60 → 移除60,加入70 → 队列元素更新(堆顶70)。
      • 60、50、40均小于堆顶70 → 不加入队列。
  4. 求和队列元素:最终队列元素为70,80,80,90,100,120,总和为70+80+80+90+100+120=540,与用例结果一致。

算法核心逻辑

通过最小优先队列动态维护最大的leftDays个日收益,利用每个城市日收益单调递减的特性(每天收益≤前一天),确保筛选出的收益是全局最优的。该方法时间复杂度为O(N×leftDays×log(leftDays)),高效适用于题目约束(N<100leftDays<T<1000)。

参考代码

class MinPriorityQueue {constructor() {this._data = [];}enqueue(e) {this._data.push(e);this.swim();}dequeue() {this._data.shift();if (this.isEmpty()) return;let lastElem = this._data.pop();this._data.unshift(lastElem);this.sink();}swim() {const n = this._data.length;let index = n - 1;while (index > 0) {let parentIndex = Math.floor((index-1)/2);if (this._data[index] < this._data[parentIndex]) {[this._data[parentIndex], this._data[index]] = [this._data[index], this._data[parentIndex]];index = parentIndex;continue;}break;}}sink() {let index = 0;const n = this._data.length;while (true) {let left = 2 * index + 1;let right = left + 1;let smallest = index;if (left < n && this._data[left] < this._data[index]) {smallest = left;}if (right < n && this._data[right] < this._data[smallest]) {smallest = right;}if (smallest !== index) {[this._data[smallest], this._data[index]] = [this._data[index], this._data[smallest]];index = smallest;continue;}break;}}top() {return this._data[0];}isEmpty() {return this._data.length === 0;}size() {return this._data.length;}
}function solution() {const [T, N] = readline().split(' ').map(Number);const times = readline().split(' ').map(Number);const cities = [];for (let i = 0; i < N; i++) {cities[i] = readline().split(' ').map(Number);}const leftDaysNum = T - times.reduce((cur,acc) => cur + acc);const profits = new MinPriorityQueue();for (let i = 0; i < N; i++) {for (let j = 0; j < leftDaysNum; j++) {let curProfit = Math.max(cities[i][0] - cities[i][1] * j, 0);if (curProfit === 0) {break;}if (profits.size() < leftDaysNum) {profits.enqueue(curProfit);} else {if (curProfit > profits.top()) {profits.dequeue();profits.enqueue(curProfit);}}}}let result = 0;while (profits.size()) {result += profits.top();profits.dequeue();}console.log(result);
}const cases = [`10 2
1 1 2
120 20
90 10`,
];let caseIndex = 0;
let lineIndex = 0;const readline = (function () {let lines = [];return function () {if (lineIndex === 0) {lines = cases[caseIndex].trim().split("\n").map((line) => line.trim());}return lines[lineIndex++];};
})();cases.forEach((_, i) => {caseIndex = i;lineIndex = 0;solution();
});

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI: 告别过时信息, 用RAG和一份PDF 为LLM打造一个随需更新的“外脑”

嘿&#xff0c;各位技术同学&#xff01;今天&#xff0c;我们来聊一个大家在使用大语言模型&#xff08;LLM&#xff09;时都会遇到的痛点&#xff1a;知识过时。 无论是像我一样&#xff0c;用 Gemini Pro 学习日新月异的以太坊&#xff0c;还是希望它能精确掌握某个特定工具…

深度学习(鱼书)day08--误差反向传播(后三节)

深度学习&#xff08;鱼书&#xff09;day08–误差反向传播&#xff08;后三节&#xff09;一、激活函数层的实现 这里&#xff0c;我们把构成神经网络的层实现为一个类。先来实现激活函数的ReLU层和Sigmoid层。ReLU层 激活函数ReLU&#xff08;Rectified Linear Unit&#xff…

C# 中生成随机数的常用方法

1. 使用 Random 类&#xff08;简单场景&#xff09; 2. 使用 RandomNumberGenerator 类&#xff08;安全场景&#xff09; 3. 生成指定精度的随机小数 C# 中生成随机数的常用方法&#xff1a; 随机数类型实现方式示例代码特点与适用场景随机整数&#xff08;无范围&#xf…

Flink 算子链设计和源代码实现

1、JobGraph &#xff08;JobManager&#xff09; JobGraph 生成时&#xff0c;通过 ChainingStrategy 连接算子&#xff0c;最终在 Task 中生成 ChainedDriver 链表。StreamingJobGraphGeneratorcreateJobGraph() 构建jobGrapch 包含 JobVertex setChaining() 构建算子链isCha…

对接八大应用渠道

背景最近公司想把游戏包上到各个渠道上&#xff0c;因此需要对接各种渠道&#xff0c;渠道如下&#xff0c;oppo、vivo、华为、小米、应用宝、taptap、荣耀、三星等应用渠道 主要就是对接登录、支付接口&#xff08;后续不知道会不会有其他的&#xff09;&#x…

学习:入门uniapp Vue3组合式API版本(17)

42.打包发行微信小程序的上线全流程 域名 配置 发行 绑定手机号 上传 提交后等待&#xff0c;上传 43.打包H5并发布上线到unicloud的前端页面托管 完善配置 unicloud 手机号实名信息不一致&#xff1a;请确保手机号的实名信息与开发者姓名、身份证号一致&#xff0c;请前往开…

SOLIDWORKS材料明细表设置,属于自己的BOM表模板

上一期我们了解了如何在SOLIDWORKS工程图中添加材料明细表?接下来&#xff0c;我们将进行对SOLIDWORKS材料明细表的设置、查看缩略图、模板保存的深度讲解。01 材料明细表设置菜单栏生成表格后左侧菜单栏会显示关于材料明细表的相关设置信息。我们先了解一下菜单栏设置详情&am…

全栈:Maven的作用是什么?本地仓库,私服还有中央仓库的区别?Maven和pom.xml配置文件的关系是什么?

Maven和pom.xml配置文件的关系是什么&#xff1a; Maven是一个构建工具和依赖管理工具&#xff0c;而pom.xml&#xff08;Project Object Model&#xff09;是Maven的核心配置文件。 SSM 框架的项目不一定是 Maven 项目&#xff0c;但推荐使用 Maven进行管理。 SSM 框架的项目可…

超越 ChatGPT:智能体崛起,开启全自主 AI 时代

引言 短短三年,生成式 AI 已从对话助手跨越到能自主规划并完成任务的“智能体(Agentic AI)”时代。这场演进不仅体现在模型规模的提升,更在于系统架构、交互范式与安全治理的全面革新。本文按时间线梳理关键阶段与核心技术,为您呈现 AI 智能体革命的脉络与未来趋势。 1. …

一杯就够:让大脑瞬间在线、让肌肉满电的 “Kick-out Drink” 全解析

一杯就够&#xff1a;让大脑瞬间在线、让肌肉满电的 “Kick-out Drink” 全解析“每天清晨&#xff0c;当闹钟还在哀嚎&#xff0c;你举杯一饮&#xff0c;睡意像被扔出擂台——这&#xff0c;就是 Kick-out Drink 的全部浪漫。”清晨 30 分钟后&#xff0c;250 mL 常温水里溶解…

系统开机时自动执行指令

使用 systemd 创建一个服务单元可以让系统开机时自动执行指令&#xff0c;假设需要执行的指令如下&#xff0c;运行可执行文件&#xff08;/home/demo/可执行文件&#xff09;&#xff0c;并输入参数&#xff08;–input/home/config/demo.yaml&#xff09;&#xff1a; /home/…

Docker 初学者需要了解的几个知识点 (七):php.ini

这段配置是 php.ini 文件中针对 PHP 扩展和 Xdebug 调试工具的设置&#xff0c;主要用于让 PHP 支持数据库连接和代码调试&#xff08;尤其在 Docker 环境中&#xff09;&#xff0c;具体解释如下&#xff1a;[PHP] extensionpdo_mysql extensionmysqli xdebug.modedebug xdebu…

【高阶版】R语言空间分析、模拟预测与可视化高级应用

随着地理信息系统&#xff08;GIS&#xff09;和大尺度研究的发展&#xff0c;空间数据的管理、统计与制图变得越来越重要。R语言在数据分析、挖掘和可视化中发挥着重要的作用&#xff0c;其中在空间分析方面扮演着重要角色&#xff0c;与空间相关的包的数量也达到130多个。在本…

dolphinscheduler中一个脚本用于从列定义中提取列名列表

dolphinscheduler中&#xff0c;我们从一个mysql表导出数据&#xff0c;上传到hdfs, 再创建一个临时表&#xff0c;所以需要用到列名定义和列名列表。 原来定义两个变量&#xff0c;不仅繁锁&#xff0c;还容易出现差错&#xff0c;比如两者列序不对。 所以考虑只定义列定义变量…

JavaWeb(苍穹外卖)--学习笔记16(定时任务工具Spring Task,Cron表达式)

前言 本篇文章是学习B站黑马程序员苍穹外卖的学习笔记&#x1f4d1;。我的学习路线是Java基础语法-JavaWeb-做项目&#xff0c;管理端的功能学习完之后&#xff0c;就进入到了用户端微信小程序的开发&#xff0c;用户端开发的流程大致为用户登录—商品浏览&#xff08;其中涉及…

灵敏度,精度,精确度,精密度,精准度,准确度,分辨率,分辨力——概念

文章目录前提总结前提 我最近在整理一份数据指标要求的时候&#xff0c;总是混淆这几个概念&#xff1a;灵敏度&#xff0c;精度&#xff0c;精确度&#xff0c;精密度&#xff0c;精准度&#xff0c;准确度&#xff0c;分辨率&#xff0c;分辨力&#xff0c;搜了一些文章&…

python-异常(笔记)

#后续代码可以正常运行 try:f open("xxx.txt","r",encodingutf-8)except:print("except error")#捕获指定异常&#xff0c;其他异常报错程序中止&#xff0c;管不到 try:print(name) except NameError as you_call:print("name error"…

[lvgl_player] 用户界面(LVGL) | 播放器核心设计

docs&#xff1a;基于LVGL的音乐播放器 本项目是为嵌入式设备设计的音乐播放系统&#xff0c;采用LVGL图形库构建用户界面。 系统支持播放WAV格式音频文件&#xff0c;具备播放列表管理功能&#xff0c;可实现播放/暂停控制、曲目切换等核心操作。 用户可通过交互界面实时调…

数据赋能(354)——数据分析——多角度分析原则

概述重要性如下&#xff1a;获得全面理解&#xff1a;多角度分析原则避免仅从单一角度解读数据&#xff0c;从不同角度、不同维度对数据进行分析&#xff0c;以获得更全面的理解。发现潜在规律&#xff1a;通过多角度分析&#xff0c;发现数据中的潜在规律和趋势&#xff0c;为…

【华为机试】127. 单词接龙

文章目录127. 单词接龙描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a;解题思路算法分析问题本质分析单向BFS算法详解双向BFS算法详解邻居单词生成过程算法流程图边界情况分析各种解法对比时间复杂度分析空间复杂度分析关键优化点实际应用场景图构建策略双向BFS优化…