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

77 阅读5分钟

问题描述

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

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

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

思路分析

defeated_count:初始化为 0,用于记录击败的怪物数量。 current_H 和 current_A:初始化为小E的初始血量和攻击力。 last_defeated_h 和 last_defeated_a:初始化为负无穷大 float('-inf'),用于记录上一个击败的怪物的血量和攻击力,便于后续进行比较。

    ## 初始化击败的怪物数量和小E的当前属性
    defeated_count = 0
    current_H = H
    current_A = A
    # 上一个击败的怪物的属性,初始设置为足够小
    last_defeated_h = float('-inf')
    last_defeated_a = float('-inf')

使用 for 循环遍历怪物列表,检查每个怪物是否可以被击败:

当前怪物的血量和攻击力是否小于小E的当前属性,并且当前怪物的血量和攻击力是否严格大于上一个击败的怪物的血量和攻击力。如果条件满足,更新小E的属性,并记录当前击败的怪物的属性。

# 遍历怪物列表,按顺序处理
    for i in range(n):
        h_i = h[i]
        a_i = a[i]
    # 检查是否可以击败当前怪物,且怪物的属性严格大于上一个击败的怪物
        if h_i < current_H and a_i < current_A and h_i > last_defeated_h and a_i > last_defeated_a:
    # 击败怪物,更新小E的属性
            current_H += h_i
            current_A += a_i
    # 更新上一个击败的怪物属性
            last_defeated_h = h_i
            last_defeated_a = a_i
    # 击败的怪物数量加一
            defeated_count += 1
        else:
            break
    return defeated_count

返回 defeated_count,即小E最多能击败的怪物数量。

注意:

这里的代码并不能解决实际问题,以下是运行结果。

image.png

这种情况是什么导致的呢?

经过分析且询问MarsCode AI,我们可以发现,代码并没有逻辑错误和语法错误,那么很可能是对输出或者是即题目意思没有理解明白。

仔细阅读,发现以上代码把 遇到了 n 个按顺序出现的怪物 这句话理解为,我们不能对怪物出现的顺序进行调整,是否这个地方理解有误?

image.png

image.png

经过询问,我们可以知道MarsCode AI也不知道该怎么理解这句话。 那么,是否对输出要求的理解有误?

根据 为了保持战斗节奏,要求击败的怪物序列中,后一个怪物的血量和攻击力都必须严格大于前一个怪物。 这句话,很可能我们需要输出的不是实际的击败数量,而是满足这个条件的怪物序列的长度。

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

若是按我们的理解,输出应该是3,若是看序列的话,就是2。 至此,我们明白问题出在哪里,那么我们重写代码。

monsters = sorted(zip(h, a)):将怪物按血量和攻击力排序。 dp = [0] * n:初始化动态规划数组 dp,用于记录击败数量。 使用 for 循环遍历怪物列表,检查每个怪物是否可以被击败。 检查条件包括:当前怪物的血量和攻击力是否小于小E的当前属性,并且当前怪物的血量和攻击力是否严格大于上一个击败的怪物的血量和攻击力。 如果条件满足,更新动态规划数组 dp

def solution(n: int, H: int, A: int, h: list, a: list) -> int:
    defeat = 0
    dp = [0] * n
    
    for i1 in range(n):
        if H > h[i1] and A > a[i1]:
            dp[i1] = 1
            
            for i2 in range(i1):
                if h[i2] < h[i1] and a[i2] < a[i1]:
                    dp[i1] = max(dp[i1], dp[i2] + 1)
            
            defeat = max(dp[i1], defeat)
    
    # 计算最终的击败序列
    max_defeat = defeat
    current_H = H
    current_A = A
    for i in range(n):
        if dp[i] == max_defeat:
            current_H += h[i]
            current_A += a[i]
            max_defeat -= 1
    
    return defeat

if __name__ == '__main__':
    print(solution(3, 4, 5, [1, 2, 3], [3, 2, 1]) == 1)
    print(solution(5, 10, 10, [6, 9, 12, 4, 7], [8, 9, 10, 2, 5]) == 2)
    print(solution(4, 20, 25, [10, 15, 18, 22], [12, 18, 20, 26]) == 3)
  • for i1 in range(n):遍历所有怪物 i1

  • if H > h[i1] and A > a[i1]:检查小E的初始血量 H 和攻击力 A 是否大于当前怪物 i1 的血量 h[i1] 和攻击力 a[i1]

  • 如果条件满足,说明小E可以击败当前怪物 i1,初始化 dp[i1] 为 1。

  • for i2 in range(i1):遍历当前怪物 i1 之前的所有怪物 i2

  • if h[i2] < h[i1] and a[i2] < a[i1]:检查当前怪物 i1 的血量和攻击力是否都大于之前的怪物 i2

  • 如果条件满足,说明当前怪物 i1 可以击败之前的怪物 i2,并且可以继续击败更多的怪物。

  • dp[i1] = max(dp[i1], dp[i2] + 1):更新当前怪物 i1 对应的最多击败数量。

  • dp[i2] + 1 表示在击败之前的怪物 i2 的基础上,再击败当前怪物 i1