华为OD机试 - 超级玛丽通过吊桥的走法 - 动态规划(Java 2024 E卷 200分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

超级玛丽好不容易来到崭新的一关,有一个长长的吊桥,吊桥的尽头是下水管道,其中随机的木板存在缺失,且踩到就会死亡,死亡后如果还有剩余的生命将任然复活且不受木板缺失影响,但会消耗一次生命,如果跨过了管道,将踏入悬崖,通关失败。

超级玛丽从起点 S 处出发,可以走到下一个木板(计1),也可以跳跃跨到下两个木板(计3),最终必须刚好走到终点 D。现在给定超级玛丽当前的生命数 M,吊桥长度的木板数 N,缺失的木板数 K 以及随机缺失的木板编号数组 L, 请帮忙计算一下,超级玛丽有多少种方法可以通过此关。

二、输入描述

第一行三个整数,超级玛丽当前生命数 M(1<=M<=5), 吊桥的长度 N(1<=N<=32, 整数),缺失木板数 K(K<=K<=32, 整数)
第二行为缺失木板编号数组 L:(长度为 K 的数组内容不大于 N 的编号数组), 1<=Li<=N, 由空格分隔的整数数组。

三、输出描述

输出通过此关的吊桥走法个数,如果不能通过此关,请输出0。

提示:

  1. 输入总是合法,忽略参数较验
  2. 必须从起点开始
  3. 必须离开吊桥到到终点。

四、测试用例

1、输入

2 2 1
2

2、输出

4

3、说明

2个生命,2个木板,缺失1个木板,缺失1个木板,第2个木板有缺失,一共有4种走法

3
1 2
2 1
1(复活)1

五、解题思路

本题适合采用动态规划(Dynamic Programming, DP)的方法来解决。

动态规划:通过状态转移方程逐步计算每个状态下的走法数,最终汇总到达终点的所有有效走法。

本题需要考虑不同路径的组合,并且每一步的选择会影响后续的走法数,符合动态规划的典型应用场景。

具体步骤如下:

  1. 状态表示:
    • 使用二维数组 dp[pos][lives] 表示到达位置 pos 时剩余生命数为 lives 的走法数。
  2. 状态转移:
    • 步进:
      • 从 pos 到 pos + 1。
      • 如果 pos + 1 是缺失木板,消耗一次生命(前提是有剩余生命)。
    • 跳跃:
      • 从 pos 到 pos + 2。
      • 如果 pos + 2 是缺失木板,消耗一次生命(前提是有剩余生命)。
  3. 初始化:
    • 起点 S 对应的位置为0,初始生命数为 M,即 dp[0][M] = 1。
  4. 目标:
    • 计算所有可能到达终点 D(位置 N + 1)的走法数。
  5. 边界条件:
    • 必须刚好走到终点 D,不能超过。
    • 如果没有足够的生命数来踩到缺失木板,则该路径不可行。

六、Java算法源码

public class OdTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取输入的三个整数:M(生命数)、N(木板数)、K(缺失木板数)
        int M = scanner.nextInt();
        int N = scanner.nextInt();
        int K = scanner.nextInt();

        // 使用HashSet存储缺失的木板编号,便于快速查询
        Set<Integer> missingPlanks = new HashSet<>();
        for(int i = 0; i < K; i++) {
            missingPlanks.add(scanner.nextInt());
        }

        // 初始化动态规划数组,dp[pos][lives]表示到达位置pos时剩余的生命数为lives的走法数
        long[][] dp = new long[N+2][M+1];
        dp[0][M] = 1; // 从起点开始,生命数为M

        // 遍历每一个位置
        for(int pos = 0; pos <= N; pos++) {
            for(int lives = 0; lives <= M; lives++) {
                if(dp[pos][lives] == 0) continue; // 如果当前状态没有走法,跳过

                // 尝试走一步到pos +1
                int step1 = pos + 1;
                if(step1 <= N) {
                    if(missingPlanks.contains(step1)) {
                        if(lives > 0) {
                            dp[step1][lives -1] += dp[pos][lives] * lives; // 消耗一个生命,有lives种选择
                        }
                    } else {
                        dp[step1][lives] += dp[pos][lives]; // 不消耗生命
                    }
                }

                // 尝试跳跃到pos +2
                int step2 = pos + 2;
                if(step2 <= N) {
                    if(missingPlanks.contains(step2)) {
                        if(lives > 0) {
                            dp[step2][lives -1] += dp[pos][lives] * lives; // 消耗一个生命,有lives种选择
                        }
                    } else {
                        dp[step2][lives] += dp[pos][lives]; // 不消耗生命
                    }
                }
            }
        }

        // 计算所有到达终点的位置的走法数之和
        long totalWays = 0;
        for(int lives = 0; lives <= M; lives++) {
            totalWays += dp[N][lives];
        }

        System.out.println(totalWays);

        // 关闭扫描器
        scanner.close();
    }
}

七、效果展示

1、输入

1 3 2
1 3

2、输出

1

3、说明

1个生命,3个木板,缺失2个木板,第1、3个木板有缺失。

只有1种走法,其他都不能通关。

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 E卷 200分)

🏆本文收录于,华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值