问题描述:给出3个参数,N,M,K,怪兽有N滴血,等着英雄来砍自己,英雄每一次打击,都会让怪兽流失[0~M]的血量,到底流失多少?每一次在[0~M]上等概率的获取一个值,求K次打击之后,英雄把怪兽砍死的概率

例如:

int N =  6;
int M = 3;
int K =  5;

解决方案:采用暴力递归加动态规划的思想

1、暴力递归:核心代码如下

public class NanDaoKillMonster {public static void main(String[] args) {int N =  6;int M = 3;int K =  5;double ans1 = killMonster(N, M, K);double ans2 = killDp1(N, M, K);double ans3 = killDp2(N, M, K);System.out.println("ans1:"+ans1+";ans2:"+ans2+";ans3:"+ans3);}private static double killMonster(int N, int M, int K) {if(N < 1 || M < 1 || K < 1){//边界验证return 0;}long all = (long) Math.pow(M + 1,K);//理想情况下打击的次数long kill = killProcess(K,M,N);//kill怪兽的次数//两者相比就是kill的概率return (double)((double)kill/(double)all);}private static long killProcess(int times, int M, int hp) {if(times == 0){//还剩0次时,验证怪兽是否打死return hp <= 0? 1:0;}if(hp <= 0){//如果怪兽已经没血了,直接返回此种情况kill的次数return (long)Math.pow(M + 1,times);}int ways = 0;for(int i = 0;i <= M;i++){//每次次数减 1,血滴数减 i,进行暴力递归ways +=killProcess(times -1,M,hp - i);}return ways;}
}

2、动态规划思想:

2.1、二维数组如图:

这是血量大于0的情况图,小于0的情况大家可以脑补一下,总之,思路是一样的。

2.2、核心代码如下:

public class NanDaoKillMonster {public static void main(String[] args) {int N =  6;int M = 3;int K =  5;double ans1 = killMonster(N, M, K);double ans2 = killDp1(N, M, K);double ans3 = killDp2(N, M, K);System.out.println("ans1:"+ans1+";ans2:"+ans2+";ans3:"+ans3);}private static double killDp1(int N, int M, int K) {if(N < 1 || M < 1 || K < 1){return 0;}long all = (long)Math.pow(M + 1,K);//理想情况下打击的次数long[][] dp = new long[K+ 1][N + 1];dp[0][0] = 1;//初始化次数for(int times = 1;times <= K;times++){//如果怪兽已经没血了,直接返回此种情况kill的次数dp[times][0] = (long)Math.pow(M + 1,times);for(int hp = 1;hp <= N;hp++){//遍历怪兽的血滴long ways = 0;/*** [0~M]比如 M = 3,* dp[5][10] 依赖dp[4][10],dp[4][9],dp[4][8],dp[4][7],* 因此有下面的循环依赖*/for(int i = 0;i <= M;i++){if(hp - i >= 0){//如果还有血滴,继续叠加ways += dp[times - 1][hp - i];}else {//如果怪兽已经没血了,直接返回此种情况kill的次数ways += (long)Math.pow(M + 1,times - 1);}}dp[times][hp] = ways;}}long kill = dp[K][N];//kill怪兽的次数//两者相比就是kill的概率return (double)((double)kill/(double) all);}}

3、升级版动态规划:

3.1、核心代码如下:

public class NanDaoKillMonster {public static void main(String[] args) {int N =  6;int M = 3;int K =  5;double ans1 = killMonster(N, M, K);double ans2 = killDp1(N, M, K);double ans3 = killDp2(N, M, K);System.out.println("ans1:"+ans1+";ans2:"+ans2+";ans3:"+ans3);}private static double killDp2(int N, int M, int K) {if(N < 1 || M < 1 || K < 1){return 0;}long all = (long)Math.pow(M + 1,K);long[][] dp = new long[K + 1][N + 1];dp[0][0] = 1;for(int times = 1;times <= K;times++){dp[times][0] = (long)Math.pow(M + 1,times);/*** 比如:* [0~M]假设 M = 7,* dp[5][10] 依赖 dp[4][10 ~ 3]八个位置的数值* dp[5][11] 依赖 dp[4][11 ~ 4]八个位置的数值 ,又等于dp[5][10] + dp[4][11] - dp[4][3]* 因此有下面的循环依赖* 总结通用公式:*      dp[i][j-1] = dp[i-1][j-1 ~ j-1-M]*      dp[i][j] = dp[i-1][j ~ j-M]*      dp[i][j] = dp[i][j-1] + dp[i-1][j] - dp[i-1][j-1-M]*      前提是血量 j>0,如果 j < 0,此种次数(M + 1)的 i即times 次方*/for(int hp = 1;hp <= N;hp++){dp[times][hp] = dp[times - 1][hp] + dp[times][hp - 1];if(hp - 1 - M >= 0){dp[times][hp] -= dp[times -1][hp - 1 -M];}else {dp[times][hp] -= Math.pow(M + 1,times - 1);}}}long kill = dp[K][N];//两者相比就是kill的概率return (double)((double)(kill)/(double)(all));}}

4、三种方案执行结果如下:

到此,该算法分享完毕,大家一定要多练习勤于思考,定会进步很快!

给出3个参数,N,M,K,怪兽有N滴血,等着英雄来砍自己,英雄每一次打击,都会让怪兽流失[0~M]的血量,到底流失多少?每一次在[0~M]上等概率的获取一个值,求K次打击之后,英雄把怪兽砍死的概率相关推荐

  1. 将投影矩阵P利用QR分解分解出摄像机内外参数(Opencv)

    将投影矩阵P利用QR分解分解出摄像机内外参数(Opencv) /***************************************************************     ...

  2. jfinal为weebox弹出框传递参数

    版权声明:欢迎转载,请注明沉默王二原创. https://blog.csdn.net/qing_gee/article/details/48712953 前言:jfinal为weebox弹出框传递参数 ...

  3. lhgdialog弹出框组件 参数详解(自己曾经开发的fuzz项目中用到过)

    lhgdialog弹出框组件 参数详解 鸣谢:http://blog.csdn.net/hurryjiang/article/details/7657623 同文:http://wjch-111.it ...

  4. lhgdialog弹出框组件 参数详解

    lhgdialog基本使用方法 : 1.下载最新版本lhgdialog: http://lhgcore.com/lhgdialog.rar 2.在需要调用lhgdialog编辑器的网页head标签结束 ...

  5. 输入圆的的半径r 和一个整型数k,当k=1 时,计算圆的面积;当k=2 时,计算圆的周长;当k = 3 时,既要求求圆的周长也要求出圆的面积

     题目:输入圆的的半径r 和一个整型数k,当k=1 时,计算圆的面积:当k=2 时,计算圆的周 长:当k = 3 时,既要求求圆的周长也要求出圆的面积. 解析:输入半径r和整型数k,由题目分析的,由于 ...

  6. layer弹出层传递参数(父传子)

    layer弹出层传递参数(父传子) 如下图所示功能 一:父页面进行ajax请求后进行渲染的js代码 二.点击管理员传值到弹出层js代码 三:弹出层html代码 == 如有不懂,请在下方留言 ==

  7. 电信行业用户流失预测——你的用户会流失吗?

    博客目的 随着通信技术的飞速发展,通信用户数量的急剧增加,通信市场趋于饱和,运营商之间的竞争愈演愈烈,使得运营商更加关注用户资源流失的问题.通过使用用户产生的数据预测潜在的流失用户,并对这些潜在的流失 ...

  8. 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂

    题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...

  9. 向模态窗体传递参数和获取返回值

    1.向window.showModalDialog 传递参数:   window.showModalDialog 方法的第二个参数就代表父窗体传递到模态窗体的参数值,可以为任何对象或数组),也可以不传 ...

最新文章

  1. Flutter——设置appBar的高度
  2. python book.save_2.3.1. 将二进制数据存为文件:saveBinDataToFile
  3. STM32 PWM输出实验
  4. javascript-定时器的使用
  5. OpenShift 4 Hands-on Lab (4) - 用ImageStream操作Image
  6. [洛谷P1908] 逆序对|归并排序|树状数组
  7. 车道线检测新工作VIL-100: A New Dataset and A Baseline Model for Video Instance Lane Detection ICCV2021
  8. 电商智能写作:京东AI闪电智能写作引擎
  9. android eclipse clean 变异,Run a clean Android build from Eclipse?
  10. 金博宝芝灵K6医药管理软件吉度盘点机PDA盘点
  11. PostgreSQL Array 数组类型与 FreeSql 打出一套【组合拳】
  12. 【Uplift】因果推断基础篇
  13. [疯狂Java]I/O:流模型(I/O流、字节/字符流、节点/处理流)
  14. 论文笔记:SRF(stereo radiance fileds)
  15. jenkins下载插件失败
  16. cv2.destoryAllWindows()无效的解决方法
  17. 计算机睡眠重启后无法识别网络,电脑睡眠后唤醒电脑没有反应
  18. Unity大场景数据加载及优化方案
  19. __align的用法
  20. golang for嵌套循环中break 的注意事项和使用细节: break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块

热门文章

  1. Java 学习(一)Java语言基础
  2. iMovie如何增加文字和图片
  3. Configuration Wizard 启动失败
  4. linux redis 查看启动命令,linux怎么启动redis
  5. 手动加载spring配置文件
  6. 如果您正在找一本关于Go语言的入门书,我只推荐您这本
  7. 通过委托的实际应用理解委托
  8. html文档头部标记,下列选项中,属于HTML文档头部相关标记的是( )。
  9. i9 9900k mysql_英特尔 i9-9900K 处理器现身跑分库:频率 5.0GHz,共有 16 线程
  10. 作为产品经理,你都是怎样思考问题的?