给出3个参数,N,M,K,怪兽有N滴血,等着英雄来砍自己,英雄每一次打击,都会让怪兽流失[0~M]的血量,到底流失多少?每一次在[0~M]上等概率的获取一个值,求K次打击之后,英雄把怪兽砍死的概率
问题描述:给出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次打击之后,英雄把怪兽砍死的概率相关推荐
- 将投影矩阵P利用QR分解分解出摄像机内外参数(Opencv)
将投影矩阵P利用QR分解分解出摄像机内外参数(Opencv) /*************************************************************** ...
- jfinal为weebox弹出框传递参数
版权声明:欢迎转载,请注明沉默王二原创. https://blog.csdn.net/qing_gee/article/details/48712953 前言:jfinal为weebox弹出框传递参数 ...
- lhgdialog弹出框组件 参数详解(自己曾经开发的fuzz项目中用到过)
lhgdialog弹出框组件 参数详解 鸣谢:http://blog.csdn.net/hurryjiang/article/details/7657623 同文:http://wjch-111.it ...
- lhgdialog弹出框组件 参数详解
lhgdialog基本使用方法 : 1.下载最新版本lhgdialog: http://lhgcore.com/lhgdialog.rar 2.在需要调用lhgdialog编辑器的网页head标签结束 ...
- 输入圆的的半径r 和一个整型数k,当k=1 时,计算圆的面积;当k=2 时,计算圆的周长;当k = 3 时,既要求求圆的周长也要求出圆的面积
题目:输入圆的的半径r 和一个整型数k,当k=1 时,计算圆的面积:当k=2 时,计算圆的周 长:当k = 3 时,既要求求圆的周长也要求出圆的面积. 解析:输入半径r和整型数k,由题目分析的,由于 ...
- layer弹出层传递参数(父传子)
layer弹出层传递参数(父传子) 如下图所示功能 一:父页面进行ajax请求后进行渲染的js代码 二.点击管理员传值到弹出层js代码 三:弹出层html代码 == 如有不懂,请在下方留言 ==
- 电信行业用户流失预测——你的用户会流失吗?
博客目的 随着通信技术的飞速发展,通信用户数量的急剧增加,通信市场趋于饱和,运营商之间的竞争愈演愈烈,使得运营商更加关注用户资源流失的问题.通过使用用户产生的数据预测潜在的流失用户,并对这些潜在的流失 ...
- 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂
题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...
- 向模态窗体传递参数和获取返回值
1.向window.showModalDialog 传递参数: window.showModalDialog 方法的第二个参数就代表父窗体传递到模态窗体的参数值,可以为任何对象或数组),也可以不传 ...
最新文章
- Flutter——设置appBar的高度
- python book.save_2.3.1. 将二进制数据存为文件:saveBinDataToFile
- STM32 PWM输出实验
- javascript-定时器的使用
- OpenShift 4 Hands-on Lab (4) - 用ImageStream操作Image
- [洛谷P1908] 逆序对|归并排序|树状数组
- 车道线检测新工作VIL-100: A New Dataset and A Baseline Model for Video Instance Lane Detection ICCV2021
- 电商智能写作:京东AI闪电智能写作引擎
- android eclipse clean 变异,Run a clean Android build from Eclipse?
- 金博宝芝灵K6医药管理软件吉度盘点机PDA盘点
- PostgreSQL Array 数组类型与 FreeSql 打出一套【组合拳】
- 【Uplift】因果推断基础篇
- [疯狂Java]I/O:流模型(I/O流、字节/字符流、节点/处理流)
- 论文笔记:SRF(stereo radiance fileds)
- jenkins下载插件失败
- cv2.destoryAllWindows()无效的解决方法
- 计算机睡眠重启后无法识别网络,电脑睡眠后唤醒电脑没有反应
- Unity大场景数据加载及优化方案
- __align的用法
- golang for嵌套循环中break 的注意事项和使用细节: break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块