当前位置: 首页 > news >正文

华为OD机试 - Wonderland游乐园 - 动态规划(Java 2024 D卷 200分)

在这里插入图片描述

华为OD机试 2024D卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》。

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

Wonderland是小王居住地一家很受欢迎的游乐园。 Wonderland目前有4种售票方式,分别为一日票(1天)、三日票(3天)、周票(7天)和月票(30天)。

每种售票方式的价格将由一个数组给出,每种票据在票面时限内可以无限制的进行游玩。例如,小王在第10日买了一张三日票,小王可以在第10日、第11日和第12日进行无限制的游玩。

小王计划在接下来一年内多次游玩该游乐园。小王计划的游玩日期将由一个数组给出。 现在,请您根据给出的售票价格数组和小王计划游玩日期数组,返回完成游玩计划所需要的最低消费。

二、输入描述

输入为2个数组

售票价格数组为costs,costs.length=4,默认顺序为一日票、三日票、周票和月票。

小王计划游玩日期数组为days,1<=days.length<=365,1<=days[i]<=365,默认顺序为升序。

三、输出描述

完成游玩计划的最低消费

四、测试用例

测试用例1:

1、输入

5 14 30 100
1 3 15 20 21 200 202 230

2、输出

40

3、说明

第1天买一张一日票:5元。
第3天买一张一日票:5元。
第15天买一张三日票:14元(覆盖15, 20, 21三天)。
第200天买一张三日票:14元(覆盖200, 202三天)。

总消费为 5 + 5 + 14 + 14 + 5 = 40。

测试用例2:

1、输入

5 14 30 100
2 4 6 8 10 12

2、输出

30

五、解题思路

1、动态规划

动态规划(Dynamic Programming, DP)是一种通过将问题分解成更小的子问题来解决复杂问题的优化方法。

动态规划常见应用:

(1)背包问题:

给定一定容量的背包和一组物品,每个物品有一定重量和价值,求背包能装下的最大价值。

(2)最长公共子序列(LCS):

求两个字符串的最长公共子序列的长度。

(3)编辑距离:

求将一个字符串变为另一个字符串所需的最小编辑操作(插入、删除、替换)的数量。

(4)硬币找零:

给定不同面值的硬币和一个总金额,求凑成该金额的最小硬币数量。

(5)斐波那契数列:

通过记忆化来计算斐波那契数列的值。

动态规划的注意事项

(1)状态定义:

需要明确每个状态代表的含义。例如,本题中 dp[i] 表示从第1天到第i天的最低花费。

(2)状态转移方程:

需要根据问题描述,建立状态转移方程。例如,本题中 dp[i] 可以通过前几天的状态加上当前天的购票费用来计算。

(3)边界条件:

需要处理好边界条件,例如数组的初始值设置、边界条件的处理等。本题中,dp[0] 初始为0,表示没有游玩时的花费为0。

(4)空间复杂度优化:

有些情况下可以通过滚动数组等方法优化空间复杂度。例如,在计算斐波那契数列时,可以只使用两个变量来保存前两个状态,而不需要完整的数组。

(5)子问题的顺序:

需要按照正确的顺序来解决子问题,通常是从最简单的子问题开始,逐步解决更复杂的子问题。

2、为什么采用动态规划?

针对本题,我们采用动态规划的原因如下:

(1)最优子结构:

动态规划适用于具有最优子结构性质的问题,即问题的最优解可以由其子问题的最优解构造而来。

在本题中,从第1天到第i天的最低花费可以通过前i天的最低花费和当天的各种购票方案来计算。

(2)重叠子问题:

动态规划特别适用于存在重叠子问题的问题,即不同的子问题会重复出现。

在本题中,从第1天到第i天的最低花费会反复计算,因此我们可以用动态规划将这些中间结果存储起来,避免重复计算,提高效率。

(3)状态转移方程:

在动态规划中,我们通过状态转移方程来逐步求解问题的最优解。

在本题中,对于每一天,我们有四种购票选择(一天票、三天票、七天票和月票),我们可以通过状态转移方程来计算每种购票方案的最小花费,从而得到全局的最小花费。

3、具体步骤:

本题的目标是根据给定的游玩日期和票价,计算出完成游玩计划所需的最低花费。我们采用动态规划(Dynamic Programming, DP)的方法来解决这个问题。具体的解题思路如下:

  1. 定义状态:
    • 我们使用一个数组 dp,其中 dp[i] 表示从第1天到第i天的最低花费。
  2. 初始化:
    • 初始化 dp[0] = 0,表示没有游玩的花费为0。
  3. 状态转移:
    • 对于每一个游玩日,我们有四种购票选择:一日票、三日票、七日票和月票。
    • 根据前面的花费情况,计算在第i天购票的最小花费,并更新 dp[i]:
    • dp[i] = min(dp[i-1] + costs[0], dp[i-3] + costs[1], dp[i-7] + costs[2], dp[i-30] + costs[3])
    • 注意边界条件处理,如果 i 小于3、7或30天时,相应的前面的花费应为0。
  4. 计算最小花费:
    • 逐日计算游玩计划的最低花费,最终得到 dp[lastPlayDay],其中 lastPlayDay 是游玩日期数组的最后一个元素。

六、Java算法源码

public class OdTest02 {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取票价数组int[] ticketPrices = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 读取游玩日期数组int[] playDays = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 获取最后一个游玩日期,即最大游玩日期int lastPlayDay = playDays[playDays.length - 1];// dp数组表示到第i天为止的最小花费,初始值为0int[] minCostUpToDay = new int[lastPlayDay + 1];// 游玩日期索引int playDayIndex = 0;// 遍历从第1天到最后一个游玩日for (int day = 1; day <= lastPlayDay; day++) {if (day == playDays[playDayIndex]) {// 如果当前日期是游玩日,有四种购票选择// 选择买“一日票”int costOneDay = minCostUpToDay[day - 1] + ticketPrices[0];// 选择买“三日票”int costThreeDay = (day >= 3 ? minCostUpToDay[day - 3] : 0) + ticketPrices[1];// 选择买“七日票”int costSevenDay = (day >= 7 ? minCostUpToDay[day - 7] : 0) + ticketPrices[2];// 选择买“月票”int costThirtyDay = (day >= 30 ? minCostUpToDay[day - 30] : 0) + ticketPrices[3];// 取上述四种票价中的最小值minCostUpToDay[day] = Math.min(Math.min(costOneDay, costThreeDay), Math.min(costSevenDay, costThirtyDay));// 移动到下一个游玩日期playDayIndex++;} else {// 如果当前日期不是游玩日,则花费与前一天相同minCostUpToDay[day] = minCostUpToDay[day - 1];}}// 输出最后一个游玩日的最小花费System.out.println(minCostUpToDay[lastPlayDay]);}
}

七、效果展示

1、输入

5 14 30 100
1 2 3 4 5 6 7 8 9 10

2、输出

44

3、说明

以下是逐天计算的过程:

第1天:买一日票,dp[1] = 5
第2天:买一日票,dp[2] = 5 + 5 = 10
第3天:买一日票,dp[3] = 10 + 5 = 15,或买三日票,dp[3] = 14,取最小值14
第4天:买一日票,dp[4] = 14 + 5 = 19
第5天:买一日票,dp[5] = 19 + 5 = 24
第6天:买一日票,dp[6] = 24 + 5 = 29,或买三日票,dp[6] = 19 + 14 = 28
第7天:买一日票,dp[7] = 28 + 5 = 33,或买三日票,dp[7] = 24 + 14 = 29,或买周票,dp[7] = 30
第8天:买一日票,dp[8] = 29 + 5 = 34,或买三日票,dp[8] = 29 + 14 = 33
第9天:买一日票,dp[9] = 34 + 5 = 39,或买三日票,dp[9] = 33 + 14 = 38
第10天:买一日票,dp[10] = 39 + 5 = 44,或买三日票,dp[10] = 38 + 14 = 42

所以,最终最小花费为 44。

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 D卷 200分)

🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 遥感领域新方向!Mamba+RS论文汇总!
  • Undertow详解
  • Spring Boot:SpringBoot入门
  • DHCP与DNS的配置
  • 【屏显MCU】多媒体接口总结
  • LNMP动态网站环境部署
  • Javascript中canvas与svg详解
  • LLM评估 | 大模型评估方法调研--论文解读(持续更新ing!!!)
  • iexcel-excel 大文件读取和写入-04-order 指定列顺序
  • Spring源码学习笔记之@Async源码
  • 智能番茄成熟度评估:基于深度学习的自动检测系统
  • AI推理硬件成本分析:AMD Instinct MI300X与Nvidia GPU比较
  • 商品中心关于缓存热key的解决方案
  • web、http协议、apache服务、nginx服务
  • 汇舟问卷:轻松入门国外问卷调查工作室
  • @jsonView过滤属性
  • [NodeJS] 关于Buffer
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • Electron入门介绍
  • ES10 特性的完整指南
  • Java 网络编程(2):UDP 的使用
  • jquery ajax学习笔记
  • LeetCode29.两数相除 JavaScript
  • Linux CTF 逆向入门
  • Meteor的表单提交:Form
  • node入门
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • yii2中session跨域名的问题
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 关于extract.autodesk.io的一些说明
  • 前端攻城师
  • 前端自动化解决方案
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 通过npm或yarn自动生成vue组件
  • 小程序测试方案初探
  • 写给高年级小学生看的《Bash 指南》
  • 进程与线程(三)——进程/线程间通信
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • # Maven错误Error executing Maven
  • (1)(1.11) SiK Radio v2(一)
  • (javascript)再说document.body.scrollTop的使用问题
  • (三)SvelteKit教程:layout 文件
  • (十) 初识 Docker file
  • (转)Sql Server 保留几位小数的两种做法
  • (转)我也是一只IT小小鸟
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Core 中插件式开发实现
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET_WebForm_layui控件使用及与webform联合使用
  • .NET程序员迈向卓越的必由之路
  • .Net的C#语言取月份数值对应的MonthName值