题目解析:小M的光明之魂速通挑战
问题描述
小M最近参加了一个名为《光明之魂》的速通比赛。在比赛中,玩家拥有N把武器以及M个Boss需要击败。规则如下:
- 每个Boss有一个唯一的类型编号,用一个正整数表示。
- 每把武器能够击败两种类型的Boss,但每把武器只能使用一次。
- 玩家必须按照给定的顺序逐个击杀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数量。
解题思路
-
武器和Boss的匹配:
- 每把武器可以击败两种Boss类型。因此,可以把武器的类型对存储为一个集合或者二维数组,表示每把武器能击败哪些Boss类型。
- 给定的Boss是按顺序出现的,因此每个Boss在队列中出现时,应该尽量选择一个尚未使用的武器来击败它。
-
贪心选择武器:
- 对于每个Boss类型,遍历所有武器,检查哪些武器能击败该Boss并且未被使用过。如果找到这样的武器,则可以将其标记为使用过,并击败该Boss。
- 我们希望最大化击败的Boss数量,因此可以按顺序逐个遍历Boss,选择一个合适的武器。
-
状态更新:
- 在每次选择了一个武器来击败某个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
}
}
代码说明
-
输入参数:
n表示武器的数量。m表示Boss的数量。boss是一个长度为m的数组,表示按顺序需要击败的Boss类型。array是一个长度为n的二维数组,每个元素表示一把武器可以击败两种Boss类型。
-
算法步骤:
-
初始化:创建一个布尔数组
usedWeapons来记录每把武器是否已经被使用。 -
逐个Boss处理:
- 遍历每个Boss,尝试为该Boss选择一个尚未使用的武器。
- 如果找到了符合条件的武器,就标记该武器为已使用,并增加击败的Boss数量。
-
如果在某个Boss的位置找不到可以击败它的武器,则跳过这个Boss。
-
-
输出结果:返回可以击败的最大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是编程学习和实践中的得力助手。