日常刷题 | 豆包MarsCode AI刷题

124 阅读3分钟

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

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

小E想知道,她最多能击败多少怪物。 要解决这个问题,我们需要找到一种策略,使得小E能够按顺序击败尽可能多的怪物,同时满足每个怪物的血量和攻击力都严格递增。我们可以使用动态规划(Dynamic Programming, DP)来解决这个问题。

思路

  1. 预处理:将怪物按照血量 h 和攻击力 a 的组合进行排序,使得我们可以按顺序检查每个怪物。
  2. 动态规划:定义一个数组 dp,其中 dp[i] 表示击败前 i 个怪物(按照排序后的顺序)时,小E能够击败的最大怪物数量。
  3. 状态转移:对于每个怪物 i,如果小E能够击败它(即 H >= h[i] 且 A >= a[i]),则检查是否可以通过击败这个怪物来获得更多的击败数量。

实现步骤

  1. 排序:将怪物按照血量 h 和攻击力 a 的组合进行排序,确保后一个怪物的血量和攻击力都严格大于前一个怪物。
  2. 初始化:初始化 dp 数组,dp[0] 为 0,因为没有怪物时击败数量为 0。
  3. 状态转移:对于每个怪物 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,可能需要进一步优化,但在这个问题的规模内是可行的。