回溯算法-以医院信息管理系统为例

1.回溯算法介绍

1.来源

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。

用回溯算法解决问题的一般步骤:

1、 针对所给问题,定义问题的解空间,它至少包含问题的一个(最优)解。

2 、确定易于搜索的解空间结构,使得能用回溯法方便地搜索整个解空间 。

3 、以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。

确定了解空间的组织结构后,回溯法就从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。 [2]

2.基本思想

回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。八皇后问题就是回溯算法的典型,第一步按照顺序放一个皇后,然后第二步符合要求放第2个皇后,如果没有位置符合要求,那么就要改变第一个皇后的位置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了。回溯在迷宫搜索中使用很常见,就是这条路走不通,然后返回前一个路口,继续下一条路。回溯算法说白了就是穷举法。不过回溯算法使用剪枝函数,剪去一些不可能到达 最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。

2.代码介绍

private static void generateMedicationCombinations() {// 存储所有药品的列表List<Medication> medications = new ArrayList<>();// 从用户那里获取药品的数量System.out.println("请输入药品数量:");int medicationCount = scanner.nextInt();scanner.nextLine(); // 读取并忽略换行符// 循环获取每种药品的详细信息for (int i = 0; i < medicationCount; i++) {System.out.println("请输入第 " + (i + 1) + " 个药品的名称:");String name = scanner.nextLine();System.out.println("请输入第 " + (i + 1) + " 个药品的剂量:");int dose = scanner.nextInt();System.out.println("请输入第 " + (i + 1) + " 个药品的价格:");int cost = scanner.nextInt();scanner.nextLine(); // 读取并忽略换行符// 将药品对象添加到列表中medications.add(new Medication(name, dose, cost));}// 从用户那里获取目标总剂量和目标总价格System.out.println("请输入目标总剂量:");int targetDose = scanner.nextInt();System.out.println("请输入目标总价格:");int targetCost = scanner.nextInt();scanner.nextLine(); // 读取并忽略换行符// 存储所有可能的药品组合的列表List<List<Medication>> combinations = new ArrayList<>();// 调用递归函数来找出所有可能的组合findCombinations(medications, new ArrayList<>(), combinations, targetDose, targetCost, 0);// 打印所有可能的药品组合System.out.println("所有可能的药品组合:");int combinationNumber = 1;for (List<Medication> combination : combinations) {int totalDose = combination.stream().mapToInt(Medication::getDose).sum();int totalCost = combination.stream().mapToInt(Medication::getCost).sum();System.out.println("第 " + combinationNumber + " 个组合:" + combination + ",总剂量:" + totalDose + ",总价格:" + totalCost);combinationNumber++;}}/*** 使用回溯算法找出所有可能的药品组合。* 函数递归地尝试添加每一种药品到当前组合中,* 并在满足条件时记录组合。*/private static void findCombinations(List<Medication> medications, List<Medication> currentCombination, List<List<Medication>> combinations, int targetDose, int targetCost, int start) {// 计算当前组合的总剂量和总成本int currentDose = currentCombination.stream().mapToInt(Medication::getDose).sum();int currentCost = currentCombination.stream().mapToInt(Medication::getCost).sum();// 如果当前组合不为空,并且其剂量和成本不超过目标值,则将其添加到组合列表中if (currentDose <= targetDose && currentCost <= targetCost && !currentCombination.isEmpty()) {combinations.add(new ArrayList<>(currentCombination));}// 如果当前组合的剂量或成本已经达到或超过目标值,则停止递归if (currentDose >= targetDose || currentCost >= targetCost) {return;}// 从start开始,尝试将每种药品添加到当前组合中for (int i = start; i < medications.size(); i++) {// 添加药品到当前组合currentCombination.add(medications.get(i));// 递归调用函数,尝试添加更多的药品findCombinations(medications, currentCombination, combinations, targetDose, targetCost, i + 1);// 回溯:从当前组合中移除最后添加的药品,为下一次迭代做准备currentCombination.remove(currentCombination.size() - 1);}}

3.使用 “回溯算法”来生成所有可能的药品组合。 

实现一个药品组合生成器,其目的是找出所有可能的药品组合,这些组合的总剂量和总价格不超过用户指定的目标剂量和目标价格。使用了回溯算法来解决这个问题。

代码中每个方法的概括:

1. `generateMedicationCombinations()`:
   - 主方法,负责程序的流程控制。
   - 首先,它初始化一个药品列表并提示用户输入药品的数量。
   - 然后,它循环提示用户输入每种药品的名称、剂量和价格,并将这些药品对象添加到列表中。
   - 接下来,它提示用户输入目标总剂量和目标总价格。
   - 调用`findCombinations()`方法来找出所有可能的药品组合,并存储在`combinations`列表中。
   - 最后,它遍历`combinations`列表并打印出每个组合及其总剂量和总价格。

2. `findCombinations(List<Medication> medications, List<Medication> currentCombination, List<List<Medication>> combinations, int targetDose, int targetCost, int start)`:
   - 递归方法,用于实现回溯算法。
   - 它接收当前药品列表、当前组合、所有组合的列表、目标剂量、目标成本以及起始索引作为参数。
   - 该方法首先计算当前组合的总剂量和总成本。
   - 如果当前组合的剂量和成本都不超过目标值,并且组合不为空,则将当前组合添加到所有组合的列表中。
   - 如果当前组合的剂量或成本已经超过目标值,则停止递归。
   - 否则,它将从`start`索引开始,尝试将每种药品添加到当前组合中,并递归调用自身。
   - 在每次递归调用之后,它会从当前组合中移除最后添加的药品,这是回溯算法的关键步骤,允许算法尝试其他可能的组合。

使用了一些关键的Java集合和流操作,例如`ArrayList`用于存储药品和组合,以及`stream().mapToInt()`用于计算总剂量和总成本。
 

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

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

相关文章

移除元素的讲解,看这篇就够了!

一&#xff1a;题目 博主本文将用指向来形象的表示下标位的移动。 二&#xff1a;思路 1&#xff1a;两个整形&#xff0c;一个start&#xff0c;一个end&#xff0c;在一开始都 0&#xff0c;即这里都指向第一个元素。 2&#xff1a;在查到val之前&#xff0c;查一个&…

Jackson与FastJson时间Date转换问题

今天在开发Excel导出时发现一个Date类型的属性导出的不对&#xff0c;因为导出时将Vo装换成了Json, Vo类Date字段也添加了DateTimeFormat(pattern "yyyy-MM-dd"),JsonFormat(timezone "GMT8", pattern "yyyy-MM-dd"),那么这是为什么呢&#…

渲染农场怎么用更省钱?渲染100邀请码1a12

现在越来越多的设计师开始使用渲染农场&#xff0c;其中收费是个大问题&#xff0c;怎么用渲染农场才能更省钱呢&#xff1f;今天我们就来看下吧。 1、明确渲染方式 要根据不同情况选择合理的渲染方式&#xff0c;比如渲染农场就适合大场景渲染和紧急出图情况&#xff0c;其他…

前端JS特效第26波:jQuery日期时间选择器插件

jQuery日期时间选择器插件&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下&#xff1a; <!DOCTYPE html> <html> <head lang"zh-CN"> <meta charset"UTF-8"> <title>jQuery日期时间选择器插件 - PHP中文网</t…

MySQL手注之布尔型盲注详解

布尔型盲注简介 基于布尔型SQL盲注即在SQL注入过程中&#xff0c;应用程序仅仅返回True&#xff08;页面&#xff09;和False&#xff08;页面&#xff09;。 这时&#xff0c;我们无法根据应用程序的返回页面得到我们需要的数据库信息。但是可以通过构造逻辑判断&#xff08;…

WSL2编译使用6.6版本内核

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、有什么变化二、下载6.6内核三、开始编译1.安装环境2.开始编译 四、使用1.杀死虚拟机2.防止内核文件3.修改配置文件 总结 前言 最近出了一件不大不小的事&a…

品牌文化五大维度,构建品牌竞争力的秘诀!

品牌文化对于企业的发展和成功至关重要。 品牌文化不仅是企业和消费者之间的纽带&#xff0c;也是企业内部员工的凝聚力。 在当今竞争激烈的市场环境中&#xff0c;建立一个有活力和影响力的品牌文化是每个企业都需要认真思考和实践的事情。 品牌文化的五大维度包括价值观、…

前端面试题31(TCP与UDP区别)

TCP (Transmission Control Protocol) 和 UDP (User Datagram Protocol) 是两种在网络通信中常用的传输层协议&#xff0c;它们在多个方面存在显著差异&#xff0c;主要体现在以下几个方面&#xff1a; 连接方式&#xff1a; TCP 是面向连接的协议。在数据传输开始之前&#xf…

数字身份管理发展趋势:IAM 和数据安全相结合

数据安全和IAM作为网络安全领域中不同的学科而存在。然而&#xff0c;随着越来越多的组织利用云服务&#xff0c;情况发生了显著的转变。许多公司现在将重要的安全控制(例如管理存储、应用程序和网络的控制)委托给他们选择的云服务提供商(CSP)。 图&#xff1a;用户与云服务商职…

oracle(表空间分类、表空间操作、默认表空间)

文章目录 oracle数据库默认表空间列表表空间是什么&#xff1f;表空间的分类1.永久性表空间&#xff1a;2.临时性表空间&#xff1a;3.撤销表空间&#xff1a; 表空间的作用Oracle 系统自动建立的表空间默认表空间1&#xff0e;SYSTEM 表空间2&#xff0e;SYSAUX表空间3&#x…

01:简易的电动车防盗报警器

简易的电动车防盗报警器 1、震动传感器模块的使用2、使用震动传感器模块控制继电器开关3、433M无线发射接收模块的使用 需要材料&#xff1a; 1、51单片机 2、震动传感器模块 3、继电器模块 4、高功率喇叭 5、433M无线发射接收模块 6、弱干杜邦线 1、震动传感器模块的使用 接好…

u盘电脑格式化恢复,这里有3种简单有效的方法和视频教程!

我们今天将探讨如何在电脑格式化后恢复U盘数据。数据丢失是一个常见问题&#xff0c;尤其是当我们需要快速清理U盘或不慎执行了格式化操作时。在本文将分享几种简单而有效的方法&#xff0c;帮助您从格式化后的U盘中恢复数据。此外&#xff0c;我们还提供了相关的视频教程&…

大话光学原理:3.干涉与衍射

一、干涉 这是一束孤独的光&#xff0c;在真空的无垠中悄无声息地穿行。忽然&#xff0c;一堵高耸的墙壁挡住了它的去路&#xff0c;它别无选择&#xff0c;只能硬着头皮冲撞而去。在摸索中&#xff0c;它意外地发现墙壁上竟有两道孔隙&#xff0c;笔直而细长&#xff0c;宛如量…

嵌入式代码升级——IAP

目录 IAP的特点 实现 IAP 功能 STM32 正常的程序运行流程 STM32 加入IAP后的运行流程 程序执行流程 BootLoader程序 APP1程序 APP2程序 验证操作步骤 IAP&#xff08;In-Application Programming&#xff09;指的是在应用程序运行时对其自身的Flash存储器进行编程的操作…

【2024——CUMCM】Matlab快速入门

目录 常识 disp and input 字符串合并 sum 提取矩阵指定位置的元素 指定行列 指定行or指定列&#xff08;返回行/列向量&#xff09; 指定某些行 指定全部元素&#xff0c;按列拼接 size repmat 矩阵的运算 基本运算 形状相同的矩阵运算 每个元素同时和常数相乘或相…

异步主从复制

主从复制的概念 主从复制是一种在数据库系统中常用的数据备份和读取扩展技术&#xff0c;通过将一个数据库服务器&#xff08;主服务器&#xff09;上的数据变更自动同步到一个或多个数据库服务器&#xff08;从服务器&#xff09;上&#xff0c;以此来实现数据的冗余备份、读…

【2】A-Frame核心设计

一、基于HTML和Primitives的表达 1.HTML - 超文本标记语言 A-Frame 基于 HTML 和 DOM 之上&#xff0c;使用自定义元素的 polyfill。 HTML 是 Web 的构建块&#xff0c;提供了最易于访问的计算语言之一。无需安装或构建步骤&#xff0c;使用 HTML 创建仅涉及 HTML 文件中的文…

【STM32/HAL】嵌入式课程设计:简单的温室环境监测系统|DS18B20 、DHT11

前言 板子上的外设有限&#xff0c;加上想法也很局限&#xff0c;就用几个传感器实现了非常简单的监测&#xff0c;显示和效应也没用太复杂的效果。虽说很简单&#xff0c;但传感器驱动还是琢磨了不久&#xff0c;加上串口线坏了&#xff0c;调试了半天才发现不是代码错了而是…

ORA-12537: TNS:连接关闭/Io 异常: Got minus one from a read call

在另外一个数据库建立dblink的时候&#xff0c;发现执行命令报错&#xff1a; 被连接的数据库我也上去过&#xff0c;用工具尝试登陆也报错&#xff1a; IO Error: Got minus one from a read call, connect lapse 1 ms., Authentication lapse 0 ms. Got minus one from a …

设计模式探索:装饰器模式

1. 装饰器模式定义 装饰器模式&#xff08;Decorator Pattern&#xff09; 装饰器模式是一种结构型设计模式&#xff0c;允许向一个对象动态添加行为。在不改变类的接口的情况下&#xff0c;装饰器模式在原始类上增加额外的职责&#xff0c;并且支持多个装饰器嵌套使用。 装…