问题描述:小E在一个游戏中遇到了 nn 个按顺序出现的怪物,每个怪物都有其特定的血量 hi 和攻击力 ai。小E的初始血量为 H,攻击力为 A。 游戏规则如下:
- 小E可以击败一个血量和攻击力都小于她当前属性的怪物。
- 对于第一个击败的怪物,需要满足其血量小于 H 且攻击力小于 A。
- 击败怪物后,小E会获得该怪物的属性值。
- 为了保持战斗节奏,要求击败的怪物序列中,后一个怪物的血量和攻击力都必须严格大于前一个怪物。
小E想知道,她最多能击败多少怪物。 要解决这个问题,我们需要找到一种策略,使得小E能够按顺序击败尽可能多的怪物,同时满足每个怪物的血量和攻击力都严格递增。我们可以使用动态规划(Dynamic Programming, DP)来解决这个问题。
思路
- 预处理:将怪物按照血量
h和攻击力a的组合进行排序,使得我们可以按顺序检查每个怪物。 - 动态规划:定义一个数组
dp,其中dp[i]表示击败前i个怪物(按照排序后的顺序)时,小E能够击败的最大怪物数量。 - 状态转移:对于每个怪物
i,如果小E能够击败它(即H >= h[i]且A >= a[i]),则检查是否可以通过击败这个怪物来获得更多的击败数量。
实现步骤
- 排序:将怪物按照血量
h和攻击力a的组合进行排序,确保后一个怪物的血量和攻击力都严格大于前一个怪物。 - 初始化:初始化
dp数组,dp[0]为 0,因为没有怪物时击败数量为 0。 - 状态转移:对于每个怪物
i,如果小E能够击败它,则更新dp[i]为dp[j] + 1的最大值,其中j是所有可以击败的怪物索引(即j < i且h[j] < h[i]且a[j] < a[i])。
代码实现
python复制代码
def max_monsters_defeated(n, H, A, h, a):
# 创建一个列表来存储怪物,每个元素是一个元组 (血量, 攻击力, 索引)
monsters = [(h[i], a[i], i) for i in range(n)]
# 按照血量和攻击力排序,如果血量相同则按攻击力排序
monsters.sort()
# 初始化 dp 数组
dp = [0] * n
# 遍历每个怪物
for i in range(n):
# 当前怪物的血量和攻击力
current_h, current_a, _ = monsters[i]
# 如果当前怪物可以被击败
if current_h <= H and current_a <= A:
# 初始化 dp[i] 为 1,因为至少可以击败这一个怪物
dp[i] = 1
# 遍历之前的所有怪物,看是否可以更新 dp[i]
for j in range(i):
prev_h, prev_a, _ = monsters[j]
# 如果前一个怪物可以被击败,并且满足递增条件
if prev_h < current_h and prev_a < current_a:
dp[i] = max(dp[i], dp[j] + 1)
# 返回 dp 数组中的最大值,即最多击败的怪物数量
return max(dp)
# 测试样例
print(max_monsters_defeated(3, 4, 5, [1, 2, 3], [3, 2, 1])) # 输出: 1
print(max_monsters_defeated(5, 10, 10, [6, 9, 12, 4, 7], [8, 9, 10, 2, 5])) # 输出: 2
print(max_monsters_defeated(4, 20, 25, [10, 15, 18, 22], [12, 18, 20, 26])) # 输出: 3
解释
- 排序:首先将所有怪物按照血量和攻击力排序,确保我们可以按顺序检查每个怪物。
- 动态规划:使用
dp数组来记录击败每个怪物时的最大击败数量。 - 状态转移:对于每个怪物,检查是否可以击败它,并更新
dp数组以记录最大击败数量。
这种方法的时间复杂度为 O(n2),因为我们需要对每个怪物检查之前的所有怪物。对于较大的 n,可能需要进一步优化,但在这个问题的规模内是可行的。