动态规划-打败怪兽的概率(java)

文章介绍了如何使用暴力递归和动态规划方法解决计算英雄在K次打击后杀死具有N滴血且每次流失0到M血量的怪兽的概率问题。提供了两种Java代码实现,分别是递归和动态规划的解决方案,并列举了其他动态规划相关的LeetCode题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

打败怪兽的概率

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

暴力递归

先把能打出伤害点数的可能性全部求出来:
long all = Math.pow(M + 1,K);
因为伤害是 0 - M 所以求所有可能性时是 M + 1
然后递归每种可能出现的伤害.

代码演示

  /**
     *
     * @param N 怪兽有N滴血,
     * @param M 英雄每一次打击, 都会让怪兽流失[0~M]的血量
     * @param K K次打击
     * @return
     */
    public static double killMonster(int N,int M,int K){
        if (N < 1 || M < 1 || K < 1) {
            return 0;
        }

        long process = process(N, M, K);
        long all = (long)Math.pow(M + 1, K);

        return  (double)process /(double)all;
    }

    /**
     * 递归
     * @param N 怪兽有N滴血,
     * @param M 英雄每一次打击, 都会让怪兽流失[0~M]的血量
     * @param K K次打击
     * @return
     */
    public static long process(int N,int M,int K){
        //base case
        if (K == 0){
            return N <= 0 ? 1 : 0;
        }
        //如果次数还没用完,怪兽就死了,那么剩下的刀数直接求可能出现的所有可能
        if (N <= 0){
            return (long)Math.pow(M + 1,K);
        }
        int ans = 0;
        //递归每种可能打出来的伤害
        for (int i = 0; i <= M;i++){
            ans += process(N - i,M,K - 1);
        }
        return ans;
    }

动态规划

对递归进行改写,先确定动态规划表如何设置,找到递归中的变量.
每次剩余的血量和砍的次数,因此二维数组就可以了.
然后改写三步骤:
1.根绝base case 初始化变量
2.递归过程改写
3.返回递归最开始调用的过程

代码演示

   /**
     * 动态规划
     * @param N 怪兽有N滴血,
     * @param M 英雄每一次打击, 都会让怪兽流失[0~M]的血量
     * @param K K次打击
     * @return
     */
    public static double hp(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];
        //base case 初始化
        dp[0][0] = 1;
        //i 是可以砍怪兽的次数
        for (int i = 1; i <= K;i++){
            //血量为0 后,如果次数还没用完,怪兽就死了,那么剩下的刀数直接求可能出现的所有可能
            dp[i][0] = (long)Math.pow(M + 1,i);
            //j 是怪兽的血量
            for (int j = 1; j <= N;j++){
                int ans = 0;
                //每次砍可能掉的血量,
                for (int hp = 0; hp <= M;hp++){
                    if (j - hp >= 0){
                        ans += dp[i - 1][j - hp];
                    }else{
                        ans +=  (long)Math.pow(M + 1,i - 1);
                    }
                }
                dp[i][j] = ans;
            }
        }
        long kill =  dp[K][N];
        return (double) kill / (double) all;
    }

动态规划专题

'leetcode688. 骑士在棋盘上的概率

凑零钱.钱币的组合有多少种

最小路径和

最长回文子序列

leetcode1143. 最长公共子序列

leetcode51. N 皇后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值