暴力递归转动态规划(十三)

题目
给定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);}

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

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

相关文章

数据结构:Map和Set(1)

搜索树 概念 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树 这棵树的中序遍历结果是有序的 接下来我们来模拟一棵二叉搜索树&#xff0c…

AD9371 官方例程裸机SW 和 HDL配置概述(二)

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

Electron[3] 基础配置准备和Electron入门案例

1 背景 上一篇文章已经分享了&#xff0c;如何准备Electron的基础环境了。但是博客刚发才一天&#xff0c;就发现有人问问题了。经过实践发现&#xff0c;严格按照作者的博客教程走是不会有问题的&#xff0c;其中包括安装的环境版本等都要一致。因为昨天发的博客&#xff0c;…

使用Jsoup库编写程序

Jsoup库编写的Kotlin网络爬虫程序 kotlin import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element import org.jsoup.select.Elements import java.net.HttpURLConnection import java.net.URL fun main(args: Array<String>) { v…

Zephyr-7B-β :类GPT的高速推理LLM

Zephyr 是一系列语言模型&#xff0c;经过训练可以充当有用的助手。 Zephyr-7B-β 是该系列中的第二个模型&#xff0c;是 Mistralai/Mistral-7B-v0.1 的微调版本&#xff0c;使用直接偏好优化 (DPO) 在公开可用的合成数据集上进行训练 。 我们发现&#xff0c;删除这些数据集的…

BIOS开发笔记 - CMOS

CMOS原来指的是一种生产电子电路的工艺,在PC上一般指的是RTC电路单元,因为早期它是由这种工艺生产出来的,所以又把RTC称作了CMOS。 RTC(Real Time Clock)即实时时钟,用于保存记录时间和日期,也可以用来做定时开机功能。RTC靠一组独立的电源给它供电,这样设计的目的就是…

Win系统强制删除文件/文件夹

Win系统强制删除文件/文件夹 前言系统磁盘清理360强制删除NPM删除 前言 Win系统的用户删除文件/文件夹时&#xff0c;可能由于权限问题导致文件无法正常删除&#xff0c;下文介绍解决方案。当常规的删除不起作用时&#xff0c;可使用如下方案进行删除&#xff0c;包含系统磁盘…

大数据商城人流数据分析与可视化 - python 大数据分析 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据的基站数据分析与可视化 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度…

若依分离版——配置多数据源(mysql和oracle),实现一个方法操作多个数据源

目录 一、若依平台配置 二、编写oracle数据库访问的各类文件 三. 一个方法操作多个数据源 一、若依平台配置 1、在ruoyi-admin的pom.xml添加oracle依赖 <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <v…

JVM 各个参数详解

在一些规模稍大的应用中&#xff0c;Java虚拟机&#xff08;JVM&#xff09;的内存设置尤为重要&#xff0c;想在项目中取得好的效率&#xff0c;GC&#xff08;垃圾回收&#xff09;的设置是第一步。 PermGen space&#xff1a;全称是Permanent Generation space.就是说是永久…

ZZ308 物联网应用与服务赛题第B套

2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 &#xff08;B卷&#xff09; 赛位号&#xff1a;______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等&#xff1b; 2.竞赛任务中所使用的…

宜昌市公安局、点军区政府与中科升哲达成战略合作,共建视频图像联合创新实验室

11月3日&#xff0c;宜昌视频图像联合创新战略合作签约仪式在宜昌市公安局举行。 宜昌市副市长、市公安局党委书记、局长上官福令&#xff0c;市公安局党委副书记、副局长龚海波&#xff0c;宜昌市点军区委书记万红&#xff0c;点军区委副书记、区长黄文云&#xff0c;升哲科技…

git commit规范提交

Git每次提交代码时&#xff0c;都要写Commit Message&#xff08;提交说明&#xff09;&#xff0c;通常情况下&#xff0c;Commit Message应该清晰明了&#xff0c;说明本次提交的目的和具体操作等。然而笔者工作多年来发现&#xff0c;有些公司对Commit Message没有明确的要求…

AI:64-基于深度学习的口罩佩戴检测

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

Luckysheet 实现excel多人在线协同编辑

前言 前些天看到Luckysheet支持协同编辑Excel&#xff0c;正符合我们协同项目的一部分&#xff0c;故而想进一步完善协同文章&#xff0c;但是遇到了一下困难&#xff0c;特此做声明哈&#xff0c;若侵权&#xff0c;请联系我删除文章&#xff01; 若侵犯版权、个人隐私&#x…

Loftware——重新定义创建、管理和打印标签的方式

重新定义创建、管理和打印标签的方式 Loftware 帮助各种规模的企业管理其运营和供应链中的标签。无论您拥有五台还是数千台打印机&#xff0c;寻找云还是本地打印机&#xff0c;我们都能提供适合您业务需求的标签解决方案。 全面的标签解决方案 01、一体化标签解决方案 通过…

【Redis】Redis整合SSMRedis注解式缓存Redis中的缓存穿透、雪崩、击穿的原因以及解决方案(详解)

目录&#xff1a; 目录 一&#xff0c;SSM整合redis 二&#xff0c;redis注解式缓存 三&#xff0c;Redis中的缓存穿透、雪崩、击穿的原因以及解决方案&#xff08;附图&#xff09; 一&#xff0c;SSM整合redis 1.原因&#xff1a; 整合SSM和Redis可以提升系统的性能、可…

桶装水订水系统水厂送水小程序开发;

桶装水小程序正式上线&#xff0c;支持多种商品展示形式&#xff0c;会员卡、积分、分销等功能&#xff1b; 开发订水送水小程序系统&#xff0c;基于用户、员工、商品、订单、配送站和售后管理模块&#xff0c;对每个模块进行统计分析&#xff0c;简化了分配过程&#xff0c;提…

vivo 网络端口安全建设技术实践

作者&#xff1a;vivo 互联网安全团队 - Peng Qiankun 随着互联网业务的快速发展&#xff0c;网络攻击的频率和威胁性也在不断增加&#xff0c;端口是应用通信中的门户&#xff0c;它是数据进出应用的必经之路&#xff0c;因此端口安全也逐渐成为了企业内网的重要防线之一&…