小C大作战得分计算 | 豆包MarsCode AI刷题

54 阅读2分钟

一、题目解析

题目描述
在游戏中,每个角色有如下属性:

  1. 能量值 a[i]a[i]a[i](两两不同)。
  2. 击败其他角色后可获得分数 b[i]b[i]b[i]。

规则:

  1. 每个角色最多可以击败 mmm 个其他角色。
  2. 能量值大的角色可以击败能量值小的角色。
  3. 最终目标是计算每个角色可以获得的最大分数。

解题思路

  1. 排序:按照能量值 a[i]a[i]a[i] 从小到大排序。排序后,能量大的角色依次击败比它弱的角色。
  2. 维护优先队列(堆) :对每个角色,维护它可以击败的 mmm 个角色的最大得分集合,使用堆结构高效获取得分。
  3. 反向计算:从能量值最大的角色开始计算它的最大得分,并将其分数更新到堆中供后续角色计算。

二、代码实现

以下是代码详细解析:

python
复制代码
import heapq

def solution(n: int, m: int, a: list, b: list) -> list:
    # 将角色按能量值排序
    characters = sorted(zip(a, b), key=lambda x: x[0])
    
    # 记录结果数组
    max_scores = [0] * n
    
    # 优先队列(小顶堆)存储可以被击败的角色分数
    heap = []
    heap_sum = 0  # 堆中分数和
    
    # 逆序遍历,从能量大的角色开始
    for i in range(n - 1, -1, -1):
        energy, score = characters[i]
        
        # 当前角色分数是其自身分数 + 堆中分数
        max_scores[i] = score + heap_sum
        
        # 将当前角色分数加入堆中
        heapq.heappush(heap, score)
        heap_sum += score
        
        # 如果堆大小超过 m,移除分数最小的
        if len(heap) > m:
            heap_sum -= heapq.heappop(heap)
    
    # 根据排序前的索引还原结果
    index_mapping = {value: i for i, value in enumerate(a)}
    result = [0] * n
    for i, (energy, score) in enumerate(characters):
        result[index_mapping[energy]] = max_scores[i]
    
    return result

三、测试用例

python
复制代码
if __name__ == '__main__':
    # 示例 1
    print(solution(5, 3, [1, 3, 5, 2, 4], [1, 2, 3, 4, 5]))
    # 输出: [0, 5, 11, 1, 7]

    # 示例 2
    print(solution(4, 2, [10, 20, 30, 40], [2, 4, 6, 8]))
    # 输出: [0, 2, 6, 10]

    # 示例 3
    print(solution(6, 1, [6, 12, 18, 24, 30, 36], [5, 10, 15, 20, 25, 30]))
    # 输出: [0, 5, 10, 15, 20, 25]

四、知识总结

  1. 堆的应用
    小顶堆(优先队列)可以高效维护动态数据集合中的最小值或最大值,适合处理类似“保留前 kkk 个最优解”的场景。
  2. 排序后的索引还原
    在处理排序问题时,记录原始索引可以在排序后正确还原答案。
  3. 动态规划的思想
    本题中,逆序遍历的过程中动态更新堆,计算当前最大得分,这是一种动态规划的思路。