小E的怪物挑战| 豆包MarsCode AI 刷题

263 阅读2分钟

这里简单讲解一下小E的怪物挑战这道题,算是一道最长上升子序列的变种。

题目大意:

小E在一个游戏中遇到了 n 个按顺序出现的怪物,每个怪物都有其特定的血量 hi 和攻击力 ai。小E的初始血量为 H,攻击力为 A。 游戏规则如下:

  1. 小E可以击败一个血量和攻击力都小于她当前属性的怪物。
  2. 对于第一个击败的怪物,需要满足其血量小于 H 且攻击力小于 A。
  3. 击败怪物后,小E会获得该怪物的属性值。
  4. 为了保持战斗节奏,要求击败的怪物序列中,后一个怪物的血量和攻击力都必须严格大于前一个怪物。

小E想知道,她最多能击败多少怪物。

测试样例(这里直接给代码中的样例了):

样例1:

输入:n=3, H=4, A=5, h=[1, 2, 3], a=[3, 2, 1]

输出:1

样例解释:

不论先击败那个怪物,都无法击败第二个

样例2:

输入:n=5, H=10, A=10, h=[6, 9, 12, 4, 7], a=[8, 9, 10, 2, 5]

输出:2

样例解释:

击败顺序为14或24或25,注意第三个怪物无法击败

样例3:

输入:n=4, H=20, A=25, h=[10, 15, 18, 22], a=[12, 18, 20, 26]

输出:3

样例解释:

击败顺序为321,注意第四个怪物无法击败

求解思路

由题意可知,小E的攻击力和血量都在击败怪物的过程中递减,求最多击败的怪物数量即找到一个最长的递减子序列。

我们可以将这个序列反转就变成了寻找最长上升子序列。在这里需要两个序列同时上升才可以算作上升。

如果没有做过最长上升子序列问题的可以先去LeetCode看看300. 最长递增子序列 - 力扣(LeetCode)

这里简单介绍一下最长上升子序列的思想。使用dp数组存储当前元素及其之前的长上升子序列的长度,使用两重循环,第一重循环从前往后枚举每个元素,第二重循环枚举该元素之前的每个元素,如果比该元素小就尝试更新dp数组。

时间复杂度O(n^2) 空间复杂度O(n)

下面是AC代码

def solution(n: int, H: int, A: int, h: list, a: list) -> int:
    # write code here
    monsters = [(0,0)]
    monsters += [(h[i], a[i]) for i in range(n) if h[i] < H and a[i] < A]

    n=len(monsters)

    dp=[0 for i in range(n+2)]

    for i in range(1,n):
        dp[i]=1
        for j in range(1,i):
            if monsters[i][0]>monsters[j][0] and monsters[i][1]>monsters[j][1]:
                dp[i]=max(dp[i],dp[j]+1)  
    return max(dp)