暴力递归转动态规划(九)

题目
题有点难,但还挺有趣
有一个咖啡机数组arr[],其中arr[i]代表每一个咖啡机冲泡咖啡所需的时间,有整数N,代表着准备冲咖啡的N个人(假设这个人拿到咖啡后喝完的时间为0,拿手里咖啡杯即变空),有一台洗咖啡杯的机器,一次只能洗一只杯子,每次洗咖啡杯消耗的时间为a,如果咖啡杯自己挥发变干净,消耗的时间是b,返回从排队开始到所有咖啡杯变干净的最短时间。

分析:

  1. 根据题意梳理后可得知,每台咖啡机冲泡咖啡是并行操作的,但是单独的咖啡机自己,是只有等当前的咖啡冲泡完成后,才可冲泡下一杯,是串行操作的。
  2. 洗咖啡杯的机器消耗时间为a,但是要等咖啡冲泡完成后,才可进行清洗。举例:1号咖啡机冲泡1杯咖啡时间为2分钟,从0时间点开始冲泡一杯咖啡,2分钟时间点结束。那么洗咖啡杯的机器是在2分钟的时间点开始工作,在2 + a时间点工作完成,才可进行下一只咖啡杯的清洗。需要注意的是:如果咖啡杯1和2都选择清洗,但是1号咖啡杯是9时间点喝完,2号咖啡杯是6时间点喝完,则2号咖啡杯在清洗时,开始的时间点是 9 + a,是根据上一直需要清洗的咖啡杯的时间来决定的。
  3. 咖啡杯自己挥发是并行操作,并且变干净的时间都是b。

暴力递归
依然是从暴力递归开始分析,并从暴力递归转换成动态规划,但是在暴力递归之前,先将这道题拆解成2道题来看。
首先是根据咖啡机数组arr和准备冲咖啡的人数N来实现一个模拟排队的功能。作用是能够获取到每个人能够最快获取到咖啡的时间点

模拟排队
模拟排队的功能实现用到了PriorityQueue,并且自己实现了咖啡机的比较规则,根据PriorityQueue的特性让效率最快的咖啡机始终在最上面并进行使用。其中(0,1)表示当前咖啡机可用时间点为0,冲泡一杯咖啡时间为1。
在这里插入图片描述

解释一下上边的图:
咖啡机数组arr{1,3,7}代表着0号咖啡机冲泡一杯咖啡所需时间为1,1号咖啡机所需时间为3,2号咖啡机所需时间为7。开始时咖啡可用时间都从0时间点开始。一共有5个人排队冲咖啡。
根据咖啡机冲泡一杯所需时间 和 咖啡机下一次可用时间 来实现咖啡机的效率最大化

所以:

  1. 第一个人过来时,会去0号咖啡机冲咖啡,此时咖啡机在1时间点冲完,并且咖啡机下次可用时间点为1。
  2. 第二个人过来时,0号咖啡机可用时间点为1,冲泡一杯咖啡所需时间为1, 1 + 1 = 2 ,小于1号咖啡机冲泡一杯的时间3,所以还是会选择0号咖啡机冲泡咖啡。
  3. 第三个人过来时,0号咖啡机会在2时间点可用,冲泡一杯咖啡时间依然是1,但是此时1号咖啡机可用时间点是0,冲泡咖啡的时间是3。此时0号咖啡机和1号咖啡机冲泡一杯咖啡结束的时间点相同(用谁都可以),我们假设用1号咖啡机,用完后,1号咖啡机可用时间点为3,**根据PriorityQueue的特性,0号咖啡机又会排到上面 **。
  4. 所以第四个人、第五个人过来都会选择0号咖啡机。

代码

public static class Machine {// 咖啡机可以工作的时间点int timePoint;//泡一杯咖啡所需时间int workTime;public Machine(int timePoint, int workTime) {this.timePoint = timePoint;this.workTime = workTime;}}//自定义比较器public static class MachineComparator implements Comparator<Machine> {@Overridepublic int compare(Machine o1, Machine o2) {return (o1.timePoint + o1.workTime) - (o2.timePoint + o2.hashCode());}}public static int forceMake(int[] arr, int N, int a, int b) {PriorityQueue<Machine> heap = new PriorityQueue<>(new MachineComparator());//初始化时,填充heapfor (int i = 0; i < arr.length; i++) {heap.add(new Machine(0, arr[i]));}//每个人最快可以喝到咖啡的数组int[] drinks = new int[N];for (int i = 0; i < N; i++) {//获取堆顶的咖啡机元素Machine curMachine = heap.poll();//咖啡机下次可用时间curMachine.timePoint += curMachine.workTime;//什么时间可以喝到咖啡drinks[i] = curMachine.timePoint;//再次压入堆中heap.add(curMachine);}//process方法是递归方法,求出咖啡杯变干净的最少时间。return process(drinks, a, b, 0, 0);}

第一个模拟排队的问题解决了,接下来就是正式的暴力递归。
暴力递归方法返回drinks[index…]位置变干净的最小时间。
所以此时base case也可以确定下来了 index == drinks.length。 而每只杯子可以选择清洗,也可以选择挥发变干净。
所以在递归向下传递时需要注意清洗咖啡杯机器的可用时间的变化。

代码
代码中在向下传递时,如果我选择了清洗,则机器的可用时间是会向后延长的,如果选择了风干,也是要根据咖啡杯的可用时间来取最大值的(木桶原理),最后,在清洗和风干中,取小的。

 	//drinks: 每个人喝到咖啡的最短时间//wash :  用洗咖啡杯机器洗一只咖啡杯的时间// air :  空气挥发一杯咖啡杯的时间//index:  第几只杯子//free : 下一次洗咖啡杯机器可用时间public static int process(int[] drink, int wash, int air, int index, int free) {//没有杯子了if (index == drink.length) {return 0;}//选择洗int selfClean1 = Math.max(drink[index], free) + wash;//向下传递,下一只杯子清洗干净的时间,此时清洗咖啡杯机器的可用时间为selfClean1int restClean1 = process(drink, wash, air, index + 1, selfClean1);//木桶原理,因为选择了清洗,所以要看当前杯子selfClean和下一个杯子restClean那个时间更大,选择哪个int p1 = Math.max(selfClean1, restClean1);// 选择风干int selfClean2 = drink[index] + air;//free依然是free,清洗咖啡杯机器的时间没有变化。int restClean2 = process(drink, wash, air, index + 1, free);//同理int p2 = Math.max(selfClean2, restClean2);//在风干和清洗中选择一个最小的。return Math.min(p1, p2);}

动态规划
根据暴力递归中的代码来改写动态规划,从暴力递归代码中可以看出,可变参数是数组下标index和清洗咖啡杯机器的freeTime。并且index的范围是 0 ~ drinks.length,需要注意的是freeTime,和之前题的可变参数范围不同。这道题中freeTime的时间范围并不好确定,需要根据具体的业务来算出来(按照drinks中最大喝完咖啡的时间 + 清洗一杯咖啡杯的时间)
所以dp[][] 初始化时,可以确定范围 dp[N + 1][maxFree]。
还需要注意的一点是,因为在遍历dp填充值的时候,内循环是遍历maxFree,而变量free是可以无限逼近maxFree的,所以在计算restClean时,需要进行判断否则很可能会有数组下标越界的情况。
而在暴力递归过程中,无论怎么清洗咖啡杯,时间都不可能大于maxFree。所以,如果计算的selfClean1变量再加完 wash后,如果 > maxFree,则证明是无效的。在实际过程中不存在这种情况。break。这个值不用填充。

public static int dp(int[] drinks, int wash, int air) {int N = drinks.length;int maxFree = 0;for (int i = 0; i < N; i++) {maxFree = Math.max(maxFree, drinks[i]) + wash;}int[][] dp = new int[N + 1][maxFree + 1];for (int index = N - 1; index >= 0; index--) {for (int free = 0; free < maxFree; free++) {int selfClean1 = Math.max(drinks[index], free) + wash;if (selfClean1 > maxFree){break;}int restClean1 = dp[index + 1][selfClean1];int p1 = Math.max(selfClean1, restClean1);int selfClean2 = drinks[index] + air;int restClean2 = dp[index + 1][free];int p2 = Math.max(selfClean2, restClean2);dp[index][free] = Math.min(p1, p2);}}return dp[0][0];}

完整代码

 public static class Machine {// 咖啡机下一次可以工作的时间int timePoint;//泡一杯咖啡所需时间int workTime;public Machine(int timePoint, int workTime) {this.timePoint = timePoint;this.workTime = workTime;}}public static class MachineComparator implements Comparator<Machine> {@Overridepublic int compare(Machine o1, Machine o2) {return (o1.timePoint + o1.workTime) - (o2.timePoint + o2.hashCode());}}public static int minTime(int[] arr, int N, int a, int b) {PriorityQueue<Machine> heap = new PriorityQueue<>(new MachineComparator());for (int i = 0; i < arr.length; i++) {heap.add(new Machine(0, arr[i]));}int[] drinks = new int[N];for (int i = 0; i < N; i++) {Machine curMachine = heap.poll();drinks[i] = curMachine.timePoint;curMachine.timePoint += curMachine.workTime;heap.add(curMachine);}return process(drinks, a, b, 0, 0);}//drinks: 每个人喝咖啡的最短时间//wash :  用洗咖啡杯机器洗一只咖啡杯的时间// air :  空气挥发一杯咖啡杯的时间//index:  第几只杯子//free : 下一次洗咖啡杯机器可用时间public static int process(int[] drink, int wash, int air, int index, int free) {//没有杯子了if (index == drink.length) {return 0;}//选择洗int selfClean1 = Math.max(drink[index], free) + wash;int restClean1 = process(drink, wash, air, index + 1, selfClean1);int p1 = Math.max(selfClean1, restClean1);// 选择风干int selfClean2 = drink[index] + air;int restClean2 = process(drink, wash, air, index + 1, free);int p2 = Math.max(selfClean2, restClean2);return Math.min(p1, p2);}public static int minTime2(int[] arr, int N, int a, int b) {PriorityQueue<Machine> heap = new PriorityQueue<>(new MachineComparator());for (int i = 0; i < arr.length; i++) {heap.add(new Machine(0, arr[i]));}int[] drinks = new int[N];for (int i = 0; i < N; i++) {Machine curMachine = heap.poll();drinks[i] = curMachine.timePoint;curMachine.timePoint += curMachine.workTime;heap.add(curMachine);}return dp(drinks, a, b);}public static int dp(int[] drinks, int wash, int air) {int N = drinks.length;int maxFree = 0;for (int i = 0; i < N; i++) {maxFree = Math.max(maxFree, drinks[i]) + wash;}int[][] dp = new int[N + 1][maxFree + 1];for (int index = N - 1; index >= 0; index--) {for (int free = 0; free < maxFree; free++) {int selfClean1 = Math.max(drinks[index], free) + wash;if (selfClean1 > maxFree){break;}int restClean1 = dp[index + 1][selfClean1];int p1 = Math.max(selfClean1, restClean1);int selfClean2 = drinks[index] + air;int restClean2 = dp[index + 1][free];int p2 = Math.max(selfClean2, restClean2);dp[index][free] = Math.min(p1, p2);}}return dp[0][0];}

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

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

相关文章

09_Webpack打包工具

1 初识Webpack 1.1 什么是Webpack Webpack打包工具对项目中的复杂文件进行打包处理&#xff0c;可以实现项目的自动化构建&#xff0c;并且给前端开发人员带来了极大的便利。 目前&#xff0c;企业中的绝大多数前端项目是基于Webpack打包工具来进行开发的。 1.2 Webpack的安…

CentOS 7系统安装配置Zabbix 5.0LTS 步骤

目录 一、查看Zabbix官方教程&#xff08;重点&#xff09; 二、安装 Docker 创建 Mysql 容器 安装 Docker 依赖包 添加 Docker 官方仓库 安装 Docker 引擎 启动 Docker 服务并设置开机自启 验证 Docker 是否成功安装 拉取 MySQL 镜像 查看本地镜像 运行容器 停止和启…

安装项目运行环境(python依赖包+allure)

目录 一、安装自动化项目依赖包1.导出项目依赖库2.上传到远程仓库3.进入jenkins容器内&#xff0c;检查是否安装git4.配置git用户信息5.生成秘钥6.把代码拉取下来7.安装python项目依赖8.运行项目 二、安装allure1.jenkins容器内安装allure&#xff0c;进入/usr/local/2.下载all…

IIS 解析漏洞复现

文章目录 IIS 解析漏洞复现1. 漏洞描述2. 漏洞复现3. 漏洞原因4. 安全加固5. 安全防护 IIS 解析漏洞复现 1. 漏洞描述 说明内容漏洞编号漏洞名称IIS 解析漏洞漏洞评级高危影响范围IIS 6.0及以前版本IIS 7.0IIS 7.5漏洞描述IIS 解析漏洞是指在 IIS 服务器上存在的安全漏洞&…

【Hello Algorithm】暴力递归到动态规划(一)

暴力递归到动态规划&#xff08;一&#xff09; 斐波那契数列的动态规划机器人走路初级递归初级动态规划动态规划 先后选牌问题初级递归初级动态规划动态规划 我们可以一句话总结下动态规划 动态规划本质是一种以空间换时间的行为 如果你发现有重复调用的过程 在经过一次之后把…

GRU的 电影评论情感分析 - python 深度学习 情感分类 计算机竞赛

1 前言 &#x1f525;学长分享优质竞赛项目&#xff0c;今天要分享的是 &#x1f6a9; GRU的 电影评论情感分析 - python 深度学习 情感分类 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 这…

git常用命令和开发常用场景

git命令 git init 创建一个空的git仓库或者重新初始化已有仓库 git clone [url] 将存储库克隆到新目录 git add 添加内容到索引 git status 显示工作树状态 git commit -m "" 记录仓库的修改 git reset 重置当前HEAD到指定的状态 git reset –-soft&#xff1a;…

【Java学习之道】Java常用集合框架

引言 在Java中&#xff0c;集合框架是一个非常重要的概念。它提供了一种方式&#xff0c;让你可以方便地存储和操作数据。Java中的集合框架包括各种集合类和接口&#xff0c;这些类和接口提供了不同的功能和特性。通过学习和掌握Java的集合框架&#xff0c;你可以更好地管理和…

Response Status Code 301、302

目录 Information Django redirect Influence Information HTTP状态码301、302和304分别表示以下情况&#xff1a; codeinformation301&#xff08;Moved Permanently&#xff09; 永久重定向。当请求的资源已经被永久地移动到了一个新的URI时&#xff0c;服务器会返回这个…

清洁洗鞋商城小程序的作用是什么

人靠衣装&#xff0c;一身干净合身的衣物总是给人赏心悦目的感觉&#xff0c;人们对颜值要求越来越高&#xff0c;不仅是衣服&#xff0c;鞋也是重要的组成部分。各种品牌样式鞋&#xff0c;很多人家里往往有几十双&#xff0c;而在清洁这一块&#xff0c;没有时间、或材质特殊…

c++视觉处理---直方图均衡化

直方图均衡化 直方图均衡化是一种用于增强图像对比度的图像处理技术。它通过重新分布图像的像素值&#xff0c;以使图像的直方图变得更均匀&#xff0c;从而提高图像的视觉质量。在OpenCV中&#xff0c;您可以使用 cv::equalizeHist 函数来执行直方图均衡化。以下是 cv::equal…

【ARM CoreLink 系列 7 -- TZC-400控制器简介】

文章目录 背景介绍1.1 TZC-400 简介1.2 TZC-400 使用示例1.3 TZC-400 interfaces1.3.1 FPID1.3.2 NSAID Regionregion 检查规则 1.4 Features1.5 Register summary1.6 TZC-400和TZPC和TZASC区别 背景介绍 为了确保内存能够正确识别总线的信号控制位&#xff0c;新增一个TrustZ…

2、TCP协议基础

TCP协议基础 1、3次握手建立连接 SYN表示建立连接的标志位&#xff0c;ACK为应答标志位 #mermaid-svg-v9bU5HHw4lMWPKc7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-v9bU5HHw4lMWPKc7 .error-icon{fill:#55222…

计算机竞赛python区块链实现 - proof of work工作量证明共识算法

文章目录 0 前言1 区块链基础1.1 比特币内部结构1.2 实现的区块链数据结构1.3 注意点1.4 区块链的核心-工作量证明算法1.4.1 拜占庭将军问题1.4.2 解决办法1.4.3 代码实现 2 快速实现一个区块链2.1 什么是区块链2.2 一个完整的快包含什么2.3 什么是挖矿2.4 工作量证明算法&…

Java 基于SpringBoot的某家乡美食系统

1 简介 《Java 基于SpringBoot的某家乡美食系统》该项目含有源码、文档等资料、配套开发软件、软件安装教程等。系统功能完整&#xff0c;适合作为毕业设计、课程设计、数据库大作业学习使用。 功能介绍 这个项目是基于 SpringBoot和 Vue 开发的地方美食系统&#xff0c;包括…

竞赛选题 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 人脸识别系统 该项目…

小谈设计模式(25)—职责链模式

小谈设计模式&#xff08;25&#xff09;—职责链模式 专栏介绍专栏地址专栏介绍 职责链模式分析角色分析抽象处理者&#xff08;Handler&#xff09;具体处理者&#xff08;ConcreteHandler&#xff09;客户端&#xff08;Client&#xff09; 优缺点分析优点123 缺点12 应用场…

当下测试行业中UI自动化面临的难点及如何解决

经常有人会问&#xff0c;什么样的项目才适合进行UI自动化测试呢&#xff1f;UI自动化测试相当于模拟手工测试&#xff0c;通过程序去操作页面上的控件。而在实际测试过程中&#xff0c;经常会遇到无法找到控件&#xff0c;或者因控件定义变更而带来的维护成本等问题。 哪些场…

深度学习基础知识 给模型的不同层 设置不同学习率

深度学习基础知识 给模型的不同层 设置不同学习率 1、使用预训练模型时&#xff0c;可能需要将2、学习率设置方式&#xff1a; 1、使用预训练模型时&#xff0c;可能需要将 &#xff08;1&#xff09;预训练好的 backbone 的 参数学习率设置为较小值&#xff0c; &#xff08;2…

Fastjson历史版本记录

1.2.24 TemplatesImpl&#xff0c;利用条件苛刻&#xff0c;需要开启Feature.SupportNonPublicField {"type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes": ["yv66vgAAADQA...CJAAk"],"_name…