华为机试题-超级玛丽过吊桥

文章描述了一个关于超级玛丽游戏的问题,玩家需要在有限生命值和缺失木板的情况下计算通关吊桥的不同走法。文章提及了一种使用map作为dp数组的动态规划解决方案来解决这个问题。
摘要由CSDN通过智能技术生成
题目

好不容易来到新的一关,有一个长长的吊桥,吊桥的尽头是下水管道,其中随机的木板存在缺失,一旦踩到就会死亡,死亡后如果还有剩余的生命将在
原地复活且不受木板缺失影响,但会消耗一次生命;如果跨过了管道,将跌入县崖,通关失败。超级玛丽从起点 S 开始,可以走到下一个木板(计 1), 也可以跳着跨过一个块(计 2)或两个木板(计 3),最终必须刚好走到终点 E. 现在给定超级玛丽当前的生命数 M,吊桥的长度 N,缺失的木板数 K,以及随机缺失的木板
编号数组 L,请帮忙计算一下,超级玛丽有多少种方法可以通过此关。
解答要求
时间限制:CIC++1000ms,其他语言:2000ms 内存限制:CIC++256MB,其他语
言:512MB
输入
超级玛丽当前生命数:M(1<=M<=5,整数)吊桥的长度:N(1=N<=32,整数)
缺失木板数:K(1<=N<=32,整数)
缺失木板编号数组:L(长度及编号的内容不大于 N 的编号数组,1<=L<=N,由空格分隔的
整数数组)
输入结构:
M N K
L
提示:
1.输入总是合法,忽略参数校验。
2 必须从起点开始走。
3.必须离开吊桥走到终点。
输出
输出通过此关的吊桥走法个数,如果不能通过此关,请输出 0
样例 1
输入:
2 2 1
2
输出: 4
解释:2 个生命,2 个木板,缺失 1 个木板
第 2 个木板有缺失,一共有 4 种走法:
13
21,2
32,1
41,1(复活).1
样例 2
输入:
1 3 2
1 3
输出:1
解释:1 个生命,3 个木板,缺失 2 个木板
第 1 个和第 3 个有缺失
只有一种走法:2,2.其他都不能通关:
1 先走 1 步,死亡;
2 先走 3 步,死亡;

参考代码

不像普通的动态规划,而是很巧妙的使用map作为dp数组

package RealTest;

/**
 * @ClassName superMary
 * @Description TODO
 * @Author 21916
 * @Date 2024/3/14 9:00
 */

import java.util.*;
import java.io.*;

public class superMary {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] input = br.readLine().split(" ");
        int M = Integer.parseInt(input[0]); // 初始生命值
        int N = Integer.parseInt(input[1]); // 吊桥长度
        int K = Integer.parseInt(input[2]); // 陷阱木板的个数

        Set<Integer> L = new HashSet<>();
        String trapInput = br.readLine();
        String[] trapSplit = trapInput.split(" ");
        for (String s : trapSplit) {
            L.add(Integer.parseInt(s));
        }

        // dp数组
        Map<Integer, Map<Integer, Integer>> dp = new HashMap<>();
        for (int i = 0; i <= N + 1; i++) {
            dp.put(i, new HashMap<>());
        }

        // 初始化起点
        dp.get(0).put(M, 1);

        // 遍历吊桥上的每个位置
        for (int i = 1; i <= N + 1; i++) {
            // 遍历i的前三个位置
            for (int j = Math.max(0, i - 3); j < i; j++) {
                // 遍历dp[j]中所有的剩余生命值
                for (Map.Entry<Integer, Integer> entry : dp.get(j).entrySet()) {
                    int rest_life = entry.getKey();
                    int ways = entry.getValue();

                    // 如果第i块木板不是陷阱木板
                    if (!L.contains(i)) {
                        // 更新dp[i][rest_life]
                        dp.get(i).put(rest_life, dp.get(i).getOrDefault(rest_life, 0) + ways);
                    }
                    // 如果第i块木板是陷阱木板,并且剩余生命值大于0
                    else if (rest_life - 1 > 0) {
                        // 更新dp[i][rest_life-1]
                        dp.get(i).put(rest_life - 1, dp.get(i).getOrDefault(rest_life - 1, 0) + ways);
                    }
                }
            }
        }

        // 累加dp[N+1]中所有值,得到到达终点的方式数
        int totalWays = 0;
        for (int count : dp.get(N + 1).values()) {
            totalWays += count;
        }
        System.out.println(totalWays);
        br.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@业精于勤荒于嬉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值