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

题目
给定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 0
        if (times == 0) {
            return hp <= 0 ? 1 : 0;
        }
        //如果在次数用没之前就已经将怪兽砍死,那么直接return
        if (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);
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

sqli-labs-1

文章目录 Less-01Less-02Less-03Less-04 Less-01 1.输入不同的id值&#xff0c;可以获取不同的用户信息&#xff1a; 2.在sql后拼接’or11–&#xff0c;并没有获取到所有用户的信息&#xff0c;猜测可能用了limit语句 3.构造错误的sql语句&#xff0c;果然有limit报错: …

深度学习中的“钩子“(Hook):基于pytorch实现了简单例子

目录 基本概念一个详细的示例 基于resnet50的一个hook应用例子前向传播示例反向传播示例 基本概念 在深度学习中&#xff0c;“钩子”&#xff08;Hook&#xff09;是一种机制&#xff0c;可以在神经网络的不同层或模块中插入自定义的代码&#xff0c;以便在网络的前向传播或反…

java传base64返回给数据报404踩坑

一、问题复现 1.可能因为base64字符太长&#xff0c;导致后端处理时出错&#xff0c;表现为前端请求报400错误&#xff1b; 这一步debug进去发现base64数据是正常传值的 所以排除掉不是后端问题,但是看了下前端请求,猜测可能是转换base64时间太长数据过大导致的404 2.前端传…

C语言求解一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

完整代码&#xff1a; /* 一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问 该数是多少&#xff1f;*/ #include<stdio.h>int main(){//num为最终所求那个数int num;//i*i为第一个完全平方数for (int i 10; …

uniapp在不需要后端数据的情况下 怎么记录用户进一次记录一次

目录 前言&#xff1a; html部分 js部分 完整代码 前言&#xff1a; 一时兴起&#xff0c;不喜勿喷&#xff0c;今天听到了这个问题想到了一个方法&#xff0c;解决方式如下。 html部分 他用于显示访问次数&#xff08;visitCount变量的值&#xff09;。 <template&…

Windows安装svn命令

1、svn命令下载地址 https://www.visualsvn.com/downloads/; 2、安装svn命令 3、测试svn命令是否安装成功

万字长文 - Python 日志记录器logging 百科全书 之 基础配置

万字长文 - Python 日志记录器logging 百科全书 之 基础配置 前言 在日常的开发中工作中&#xff0c;日志记录扮演着不可或缺的角色。它不仅能让我们了解应用程序的运行状况&#xff0c;还能帮助我们定位并解决各种问题。 最基本的&#xff0c;它记录了应用程序的运行情况&am…

【论文阅读】Progressive Spatio-Temporal Prototype Matching for Text-Video Retrieval

资料链接 论文链接&#xff1a;https://openaccess.thecvf.com/content/ICCV2023/papers/Li_Progressive_Spatio-Temporal_Prototype_Matching_for_Text-Video_Retrieval_ICCV_2023_paper.pdf 代码链接&#xff1a;https://github.com/imccretrieval/prost 背景与动机 文章发…

百分点科技受邀参加“第五届治理现代化论坛”

11月4日&#xff0c;由北京大学政府管理学院主办的“面向新时代的人才培养——第五届治理现代化论坛”举行&#xff0c;北京大学校党委常委、副校长、教务长王博&#xff0c;政府管理学院院长燕继荣参加开幕式并致辞&#xff0c;百分点科技董事长兼CEO苏萌受邀出席论坛&#xf…

Spring Cloud学习(二)【Eureka注册中心】

文章目录 Eureka 注册中心Eureka 的作用 动手实践搭建 EurekaServer服务注册服务发现 Ribbon 负载均衡负载均衡原理IRule 接口&#xff08;负载均衡策略&#xff09;饥饿加载 Eureka 注册中心 服务调用出现的问题 不能采用硬编码服务消费者该如何获取服务提供者的地址信息&am…

06【保姆级】-GO语言的运算符

之前我学过C、Java、Python语言时总结的经验&#xff1a; 先建立整体框架&#xff0c;然后再去抠细节。先Know how&#xff0c;然后know why。先做出来&#xff0c;然后再去一点点研究&#xff0c;才会事半功倍。适当的囫囵吞枣。因为死抠某个知识点很浪费时间的。对于GO语言&a…

JDBC(二)

第4章 操作BLOB类型字段 4.1 MySQL BLOB类型 MySQL中&#xff0c;BLOB是一个二进制大型对象&#xff0c;是一个可以存储大量数据的容器&#xff0c;它能容纳不同大小的数据。 插入BLOB类型的数据必须使用PreparedStatement&#xff0c;因为BLOB类型的数据无法使用字符串拼接写…

OAuth 2.0实现统一认证

OAuth 2.0协议概念&#xff1a; OAuth 是 Open Authorization 的简写。OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 OAuth 的授权不会使第三方触及到用户的帐号信息&#xff08;如用户名与密码&#xff09;&#xff0c;即第…

Kotlin HashMap entries.filter过滤forEach

Kotlin HashMap entries.filter过滤forEach fun main(args: Array<String>) {val hashMap HashMap<String, Int>()hashMap["a"] 1hashMap["b"] 2hashMap["c"] 3println(hashMap)hashMap.entries.filter {println("filter $…

【MongoDB】索引 – 文本索引(指定语言)

一、语言列表 语言名称 代码 danish da dutch nl english en finnish fi french fr german de hungarian hu italian it norwegian nb portuguese pt romanian ro russian ru spanish es swedish sv turkish tr 二、指定默认语言 创建文本索…

UseGalaxy.cn生信云平台文本文件操作手册

文本文件是生物信息学中应用非常广泛的文本格式&#xff0c;甚至可以说是最重要的文件格式&#xff0c;比如常见的测序下机数据Fastq、参考基因组保存格式Fasta、比对文件SAM&#xff0c;以及突变列表VCF&#xff0c;它们都是文本文件。熟练地进行文本文件的处理&#xff0c;对…

upload-labs-1

文章目录 Pass-01 Pass-01 先上传一个正常的图片&#xff0c;查看返回结果&#xff0c;结果中带有文件上传路径&#xff0c;可以进行利用&#xff1a; 上传一个恶意的webshell&#xff0c;里面写入一句话木马&#xff1a; <?php eval($_POST[cmd]); echo "hello&quo…

【单片机】初次实验:Keil51的使用

哔哩哔哩/CSDN/博客园&#xff1a;萌狼蓝天 延时器 delay(int count){int i,j;for(i0;i<count;i){for(j0;j<1000;j);} } 瞧一瞧 题目要求&#xff1a;P0口接八个发光二极管&#xff0c;先让后面四个灯亮&#xff0c;再让前面四个灯亮&#xff0c;循坏 # include <REGX…

京东数据分析(京东销量):2023年9月京东投影机行业品牌销售排行榜

鲸参谋监测的京东平台9月份投影机市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台的相关数据数据显示&#xff0c;9月份&#xff0c;京东平台投影机的销量为13万&#xff0c;环比下滑约17%&#xff0c;同比下滑约25%&#xff1b;销售额将近2.6亿&#xff0c;环比下…

eNsp下如何使用wireshark抓包

文章目录 拓扑图抓包操作 拓扑图 抓包操作 可以通过下图上的指示 来设置 Time列的显示样式。 这里有个缺点就是就是抓取ensp上的虚拟设备上的数据包时的&#xff0c;年月日时间显示的不对。暂时无解决办法。 一般选择 日期和时间&#xff08;日期和时间与当前标准时间对应上时…