暴力递归转动态规划(十三)
题目
给定3个参数,N,M,K
怪兽有N滴血,等着英雄来砍自己
英雄每一次打击,都会让怪兽流失[0~M]的血量
到底流失多少?每一次在[0~M]上等概率的获得一个值
求K次打击之后,英雄把怪兽砍死的概率。
暴力递归
先确定好暴力递归的尝试方法,并根据方法确定base case。
已知参数是 N:怪兽血量 M:每次等概率砍0 ~ M滴血 K:砍K次。
所以如果暴力递归方法返回在hp滴血情况下,砍times次,每次砍0 ~ M滴血。能将怪兽砍死的方法数。
其中hp:剩余血量 。 tmies:剩余砍的次数。M固定不变。
代码
递归方法就如上面所描述的递归方法进行的尝试,每次砍都等概率掉 0 ~ M滴血(for循环表示),每次掉血后,继续相加递归(次数 times - 1, hp - i 为剩余血量),砍当前砍掉 i 滴血后,能砍死怪兽的方法。
base case : 当次数为0时,如果hp <= 0 ,则return 1,证明怪兽gg,否则返回0,证明当前情况下没砍死怪兽。
需要注意的是,times不为0,但是怪兽 hp <= 0 的情况。
比如说:怪兽hp = 3 。times = 4 还可砍击4次,每次掉 0 ~ 5滴血。
可能我第一刀的时候就砍了5滴血。剩下的3次无论怎么砍,都会成功,怪兽都已经是GG的状态。
此时,就运用到了之前我们所说的“剪枝”的优化技巧。
剩下的几刀都没有必要再进行递归方法向下调用。但是每次 0 ~ M滴血,就是一个M + 1的展开情况,剩余 times = 3。
直接可求得剩余击杀怪兽的方法数 = Math.pow(M + 1, times);
public static double right(int N, int M, int K) {if (N < 1 || M < 1 || K < 1) {return 0;}//砍怪兽的总方法数:每次都是 0 ~ M滴血,所以是 M + 1的展开,能砍K次。double all = Math.pow(M + 1, K);//击杀怪兽的方法数。double kill = (double) process(K, M, N);return kill / all;}public static double process(int times, int M, int hp) {//如果剩余次数为0,此时剩余血量 <= 0,代表把怪兽砍死,return 1,否则return 0if (times == 0) {return hp <= 0 ? 1 : 0;}//如果在次数用没之前就已经将怪兽砍死,那么直接returnif (hp <= 0) {return Math.pow(M + 1, times);}int ways = 0;//否则,等概率的砍,每一刀砍的范围 0 ~ M。每砍一刀,次数 - 1。for (int i = 0; i <= M; i++) {ways += process(times - 1, M, hp - i);}return ways;}
动态规划
根据上面暴力递归的代码可以看出,可变参数为 hp:怪兽剩余血量 。 times:剩余砍击次数。又因为hp和times都可以到达0。所以可以确定dp表是一个二维数组,以及范围是dp[K + 1][N + 1]。(K,N为题意所给的血量和次数)。
根据暴力递归的base case,当次数为0时,hp如果为0,则return 1。所以可以确定dp[0][0] = 1
if (times == 0) {return hp <= 0 ? 1 : 0;}
根据这行base case,也可以确定,dp[0][hp] = Math.pow(M + 1, times);。
if (hp <= 0) {return Math.pow(M + 1, times);
}
其余代码照搬暴力递归即可。
完整代码
遍历过程中,hp会有负数的可能,需要注意并进行判断。因为dp表大小是dp[K + 1][N + 1],此时如果要考虑负数的因素就要扩大N + 1的返回,增加判断,很麻烦。
所以要对hp - i 进行判断, 如果 hp - i >= 0 则从dp表中取。如果 hp - i < 0。则直接从我们的公式 Math.pow(M + 1, times - 1);中取,times - 1是因为当前第times次砍击砍下来后hp - i < 0,剩余times - 1次肯定就是成功的情况。
public static double dp(int N, int M, int K) {if (N < 1 || M < 1 || K < 1) {return 0;}double all = Math.pow(M + 1, K);int[][] dp = new int[K + 1][N + 1];dp[0][0] = 1;for (int times = 1; times <= K; times++) {dp[times][0] = (int) Math.pow(M + 1, times);for (int hp = 1; hp <= N; hp++) {int ways = 0;for (int i = 0; i <= M; i++) {if (hp - i >= 0) {ways += dp[times - 1][hp - i];} else {ways += (int) Math.pow(M + 1, times - 1);}}dp[times][hp] = ways;}}return (double)((double)dp[K][N] / (double)all);}
再次优化
可以看到,动态规划的过程中出现了枚举行为(for循环 0 ~ M滴血),所以如果找到dp表中每个格子间的依赖关系,那么还有进一步的优化空间。
以下图为例:假设,当前times = 2 还剩2次机会,hp = 3 剩余3滴血,M = 3 每次等概率掉 0 ~ 3滴血。
根据暴力递归中依赖关系是 times - 1,hp - i ,i = 0 ~ 3,所以想要求得dp[2][3]格子 √ 处的值需要依赖dp[1,0] ~ dp[1,4]四个格子的累加。

求√’处的值,hp = 4,依然是剩余2次机会,每次 0 ~ 3,依赖的就是dp[1,1] ~ dp[1][4]的值,那此时如果用 √ + dp[1][4] - dp[1][0],是不是就省去了再求dp[1][1] ~ dp[1][3]的过程。
我们将此过程抽象化一下,就是优化后的代码。

优化代码
同样要考虑hp负数的问题,如果hp为负数,则前面的也要减掉。
如图:求 √ 位置时,依赖的X已经越界了,那么此时,利用公式Math.pow(M + 1, times - 1);减掉前面的位置。

public static double bestDP(int N, int M, int K) {if (N < 1 || M < 1 || K < 1) {return 0;}double all = Math.pow(M + 1, K);int[][] dp = new int[K + 1][N + 1];dp[0][0] = 1;for (int times = 1; times <= K; times++) {dp[times][0] = (int) Math.pow(M + 1, times);for (int hp = 1; hp <= N; hp++) {dp[times][hp] = dp[times][hp - 1] + dp[times - 1][hp];if (hp - M - 1 <= 0) {dp[times][hp] -= Math.pow(M + 1, times - 1);} else {dp[times][hp] -= dp[times - 1][hp - M - 1];}}}return (double) ((double) (dp[K][N]) / all);}
相关文章:
暴力递归转动态规划(十三)
题目 给定3个参数,N,M,K 怪兽有N滴血,等着英雄来砍自己 英雄每一次打击,都会让怪兽流失[0~M]的血量 到底流失多少?每一次在[0~M]上等概率的获得一个值 求K次打击之后,英雄把怪兽砍死的概率。 暴…...
java EE 进阶
java EE 主要是学框架(框架的使用,框架的原理) 框架可以说是实现了部分功能的半成品,还没装修的毛坯房,然后我们再自己打造成自己喜欢的成品 这里学习四个框架 : Spring ,Spring Boot, Spring MVC, Mybatis JavaEE 一定要多练习,才能学好 Maven 目前我们主要用的两个功能: …...
记录paddlepaddle-gpu安装
背景 由于最近需要使用paddleocr,因此需要安装依赖paddlepaddle-gpu,不管怎么安装cuda11.6-11.8安装了一遍,都无法正常安装成功。如下所示: 环境:wsl2linux18.04 >>> import paddle >>> paddle.u…...
django如何连接sqlite数据库?
目录 一、SQLite数据库简介 二、Django连接SQLite数据库 1、配置数据库 2、创建数据库表 三、使用Django ORM操作SQLite数据库 1、定义模型 2、创建对象 3、查询对象 总结 本文将深入探讨如何在Django框架中连接和使用SQLite数据库。我们将介绍SQLite数据库的特点&…...
面试算法47:二叉树剪枝
题目 一棵二叉树的所有节点的值要么是0要么是1,请剪除该二叉树中所有节点的值全都是0的子树。例如,在剪除图8.2(a)中二叉树中所有节点值都为0的子树之后的结果如图8.2(b)所示。 分析 下面总结什么样的节…...
云安全-云原生k8s攻击点(8080,6443,10250未授权攻击点)
0x00 k8s简介 k8s(Kubernetes) 是容器管理平台,用来管理容器化的应用,提供快速的容器调度、弹性伸缩等诸多功能,可以理解为容器云,不涉及到业务层面的开发。只要你的应用可以实现容器化,就可以部…...
性能压力测试主要目标及步骤
性能压力测试是软件开发生命周期中至关重要的一部分,旨在评估应用程序或系统在高负载和极端条件下的性能表现。这种测试有助于发现性能瓶颈、资源耗尽和错误,以确保应用程序在真实使用情况下的可靠性和稳定性。本文将探讨性能压力测试的概念、方法和最佳…...
VLAN与配置
VLAN与配置 什么是VLAN 以最简单的形式为例。如下图,此时有4台主机处于同一局域网中,很明显这4台主机是能够直接通讯。但此时我需要让处于同一局域网中的PC3和PC4能通讯,PC5和PC6能通讯,并且PC3和PC4不能与PC5和PC6通讯。 为了实…...
API接口安全设计
简介 HTTP接口是互联网各系统之间对接的重要方式之一,使用HTTP接口开发和调用都很方便,也是被大量采用的方式,它可以让不同系统之间实现数据的交换和共享。 由于HTTP接口开放在互联网上,所以我们就需要有一定的安全措施来保证接口…...
服务器的管理口和业务口
服务器管理接口和业务接口 服务器管理接口(Server Management Interface,SMI): 服务器管理接口是一种用于管理服务器硬件和操作系统的标准接口。它通常用于远程管理和监控服务器,包括但不限于以下功能: …...
【gpt redis】原理篇
用的黑马程序员redis课程的目录,但是不想听讲了。后续都是用gpt文档获取的。 1.课程介绍(Av766995956,P145) 2.Redis数据结构-动态字符串(Av766995956,P146) sds 1M是个界限 其实他是个由c语言实现的结构体 有这么几个参数 len alloc flag char[] len是实际长度 …...
python二次开发Solidworks:排雷以及如何排雷?
目录 1、重要文档 2、MSDN VARIANTS 3、错误排除实例 3.1 第一个例子 3.2 第二个例子 1、重要文档 SolidWorks API 帮助文档:在 SolidWorks 的安装路径下可以找到本地文件,如 ...\Program Files\SolidWorks Corp\SolidWorks\api\apihelp.chm 。 s…...
广告引擎检索技术快速学习
目录 一、广告系统与广告引擎介绍 (一)广告系统与广告粗分 (二)广告引擎在广告系统中的重要性分析 二、广告引擎整体架构和工作过程 (一)一般概述 (二)核心功能架构图 三、标…...
Scala的类和对象
1. 初识类和对象 Scala 的类与 Java 的类具有非常多的相似性,示例如下: // 1. 在 scala 中,类不需要用 public 声明,所有的类都具有公共的可见性 class Person {// 2. 声明私有变量,用 var 修饰的变量默认拥有 getter/setter 属性private var…...
SQL中 <>(不等于)运算符只会匹配那些具有非空值的记录
0. 场景 idflag112null3 一张表的有有个varchar类型的flag字段,字段值有 null值/空值和 1。 flag为 1即表示逻辑删除,我想找出flag字段非 1 的所有情况: 一开始sql写法: select * from table where flag<>‘1’理想情况,结果集应该有2条记录(id为 2 和 3 的记录)实际情…...
冒泡排序(Java)
基本思想 比较前后相邻的二个数据,如果前面数据大于后面的数据,就将这二个数据交换。这样对数组的第 0 个数据到 N-1 个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1 个位置。如此循环 (N-1)次,每次循环需要比较的个数…...
k8s集群调度
目录 1、理论: 1.1、 概述: 1.2、Pod 是 Kubernetes 的基础单元,Pod 启动典型创建过程如下: 工作机制 **** 1.3、调度过程 *** 1.4、Predicate 有一系列的常见的算法可以使用: ** 1.5、 优先级由一系列键…...
Scala中类的继承、抽象类和特质
1. 类的继承 1.1 Scala中的继承结构 Scala 中继承关系如下图: Any 是整个继承关系的根节点; AnyRef 包含 Scala Classes 和 Java Classes,等价于 Java 中的 java.lang.Object; AnyVal 是所有值类型的一个标记; Nul…...
小程序如何实现登录数据持久化
在小程序中实现登录数据的持久化可以通过以下几种方式: 使用本地缓存 在用户登录成功后,将登录凭证或用户信息等数据使用 wx.setStorageSync 方法存储到本地缓存中: // 存储登录数据到本地缓存 wx.setStorageSync(token, 登录凭证); wx.set…...
Maven本地配置获取nexus私服的依赖
场景 Nexus-在项目中使用Maven私服,Deploy到私服、上传第三方jar包、在项目中使用私服jar包: Nexus-在项目中使用Maven私服,Deploy到私服、上传第三方jar包、在项目中使用私服jar包_nexus maven-releases 允许deploy-CSDN博客 在上面讲的是…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
