小M的光明之魂速通挑战| 豆包MarsCode AI 刷题

176 阅读6分钟

题目解析:小M的光明之魂速通挑战

问题描述

小M最近参加了一个名为《光明之魂》的速通比赛。在比赛中,玩家拥有N把武器以及M个Boss需要击败。规则如下:

  1. 每个Boss有一个唯一的类型编号,用一个正整数表示。
  2. 每把武器能够击败两种类型的Boss,但每把武器只能使用一次。
  3. 玩家必须按照给定的顺序逐个击杀Boss,不能跳过Boss顺序。

小M想知道,在不违反规则的前提下,他最多能够击败多少个Boss。

输入变量说明:

  • n 表示拥有的武器数量。
  • m 表示需要击败的Boss数量。
  • boss 是一个长度为m的列表,表示玩家必须按照顺序击杀的Boss的类型。
  • array 是一个长度为n的二维列表,每个元素为 [x, y],表示对应的武器可以击败类型为 x 和 y 的Boss。

测试样例

样例1:

输入:n = 3 ,m = 5 ,boss = [1, 2, 3, 4, 5] ,array = [[1, 2], [3, 2], [4, 5]]
输出:2

样例2:

输入:n = 3 ,m = 5 ,boss = [4, 3, 2, 1, 5] ,array = [[1, 2], [3, 2], [4, 5]]
输出:3

样例3:

输入:n = 4 ,m = 6 ,boss = [1, 2, 3, 4, 5, 6] ,array = [[1, 2], [2, 3], [3, 4], [5, 6]]
输出:3

问题分析

题目给定了一个速通比赛的规则,玩家有若干把武器,每把武器可以击败两种不同类型的Boss,且每个Boss类型是一个正整数。玩家需要按照给定的顺序击败Boss,而每把武器只能用一次,且每个Boss只能用一把武器击败。

目标是求在不违反规则的情况下,玩家最多能够击败多少个Boss。

问题的核心

  • 武器选择:每把武器只能击败两种类型的Boss,且玩家不能跳过Boss的顺序,因此需要根据每个Boss类型来选择合适的武器。
  • Boss顺序:玩家必须按顺序击败给定的Boss列表中的每个Boss,不能跳过。

因此,问题可以被视作一个贪心选择的过程:尽量选择最合适的武器来击败Boss,以最大化击败的Boss数量。

解题思路

  1. 武器和Boss的匹配

    • 每把武器可以击败两种Boss类型。因此,可以把武器的类型对存储为一个集合或者二维数组,表示每把武器能击败哪些Boss类型。
    • 给定的Boss是按顺序出现的,因此每个Boss在队列中出现时,应该尽量选择一个尚未使用的武器来击败它。
  2. 贪心选择武器

    • 对于每个Boss类型,遍历所有武器,检查哪些武器能击败该Boss并且未被使用过。如果找到这样的武器,则可以将其标记为使用过,并击败该Boss。
    • 我们希望最大化击败的Boss数量,因此可以按顺序逐个遍历Boss,选择一个合适的武器。
  3. 状态更新

    • 在每次选择了一个武器来击败某个Boss后,需要将该武器标记为已经使用过,不能再次使用。

代码实现

javaCopy Code
public class Main {
    public static int solution(int n, int m, int[] boss, int[][] array) {
        // 用一个数组来记录每个武器是否已被使用,初始时都是未使用
        boolean[] usedWeapons = new boolean[n];
        int defeatedBossCount = 0;
        
        // 遍历每个Boss
        for (int i = 0; i < m; i++) {
            int currentBoss = boss[i];
            boolean bossDefeated = false;
            
            // 尝试选择一个尚未使用的武器击败当前Boss
            for (int j = 0; j < n; j++) {
                if (!usedWeapons[j] && (array[j][0] == currentBoss || array[j][1] == currentBoss)) {
                    // 如果武器j可以击败当前Boss并且没有被使用过
                    usedWeapons[j] = true;  // 标记武器已使用
                    defeatedBossCount++;    // 成功击败一个Boss
                    bossDefeated = true;
                    break;  // 找到合适的武器后,跳出内层循环
                }
            }
            
            // 如果没有武器能够击败当前Boss,则跳过
            if (!bossDefeated) {
                continue;
            }
        }
        
        // 返回最大能够击败的Boss数量
        return defeatedBossCount;
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(solution(3, 5, new int[]{1, 2, 3, 4, 5}, new int[][]{{1, 2}, {3, 2}, {4, 5}}) == 2);  // 结果是 2
        System.out.println(solution(3, 5, new int[]{4, 3, 2, 1, 5}, new int[][]{{1, 2}, {3, 2}, {4, 5}}) == 2);  // 结果是 2
    }
}

代码说明

  1. 输入参数

    • n 表示武器的数量。
    • m 表示Boss的数量。
    • boss 是一个长度为 m 的数组,表示按顺序需要击败的Boss类型。
    • array 是一个长度为 n 的二维数组,每个元素表示一把武器可以击败两种Boss类型。
  2. 算法步骤

    • 初始化:创建一个布尔数组 usedWeapons 来记录每把武器是否已经被使用。

    • 逐个Boss处理

      • 遍历每个Boss,尝试为该Boss选择一个尚未使用的武器。
      • 如果找到了符合条件的武器,就标记该武器为已使用,并增加击败的Boss数量。
    • 如果在某个Boss的位置找不到可以击败它的武器,则跳过这个Boss。

  3. 输出结果:返回可以击败的最大Boss数量。

复杂度分析

  • 时间复杂度:遍历每个Boss需要 O(m),对于每个Boss,需要遍历所有武器,时间复杂度为 O(n)。因此总的时间复杂度为 O(n * m),其中 n 是武器数量,m 是Boss数量。
  • 空间复杂度:使用了一个布尔数组 usedWeapons 来记录武器是否使用过,所以空间复杂度是 O(n)

例子分析

输入:

javaCopy Code
solution(3, 5, new int[]{1, 2, 3, 4, 5}, new int[][]{{1, 2}, {3, 2}, {4, 5}});
  • 玩家有3把武器:

    • 武器1:可以击败Boss类型1和Boss类型2。
    • 武器2:可以击败Boss类型3和Boss类型2。
    • 武器3:可以击败Boss类型4和Boss类型5。
  • 玩家需要按顺序击败的Boss是:1, 2, 3, 4, 5。

流程

  • 第一个Boss是类型1,武器1可以击败它,因此选择武器1。
  • 第二个Boss是类型2,武器2可以击败它,因此选择武器2。
  • 第三个Boss是类型3,武器2已经被用过,因此武器3可以击败它,选择武器3。
  • 第四个Boss是类型4,武器3已经被用过,没有武器可以击败类型4的Boss。
  • 第五个Boss是类型5,武器3已经被用过,因此没有武器可以击败类型5的Boss。

最大击败的Boss数量:2

输出:

Copy Code
2

心得:

使用MarsCode AI编写代码让我体验到了编程的便利与高效。AI能够快速生成代码示例,帮助我理解不同编程概念。通过交互式的反馈,我能迅速调整思路,解决问题。同时,MarsCode AI提供的建议让我了解到更多最佳实践,提升了我的编码水平。这种工具不仅节省了时间,还激发了我的创造力,尤其是在处理复杂问题时,AI的支持显得尤为重要。总的来说,MarsCode AI是编程学习和实践中的得力助手。