247 小X的勇士打怪游戏 题解 | 豆包MarsCode AI刷题

135 阅读3分钟

问题描述

小强在玩一款勇士打怪游戏,勇者和怪物都有能力值。当勇者的能力值不低于当前怪物的能力值时,勇者可以击败怪物并获得一枚金币。如果勇者能力值不够,他可以使用一枚金币来增加1点能力值,但金币不能为负。勇者可以选择任意顺序与怪物战斗。小强想知道,在打败一部分怪物后,勇者最多能积累多少金币。

题目分析

这个问题可以看作是一个动态规划问题,其中需要最大化勇者获得的金币数量。关键点是,勇者可以自由选择与哪些怪物战斗,以及在必要时使用金币增加自己的能力值。

  1. 排序:首先,对怪物的能力值进行排序,这样可以保证在动态规划过程中,勇者面对的是越来越强的怪物,从而简化状态转移的逻辑。

  2. 状态定义:定义一个数组 gold,其中 gold[i] 表示在与前 i 个怪物战斗后,勇者最多能积累的金币数量。

  3. 状态转移

    • 如果勇者的当前能力值 a 大于或等于第 i 个怪物的能力值,那么可以直接击败这个怪物,并获得一枚金币。此时,gold[i] = gold[i-1] + 1

    • 如果勇者的当前能力值 a 小于第 i 个怪物的能力值:

      1. 假设花费 k 枚金币后,勇者的能力值刚好可以击败这个怪物,则 k = monsters[i] - a

      2. 如果 k <= gold[i-1],则可以进行战斗,即gold[i] = gold[i-1] - k + 1(减去花费的金币,加上战斗获得的金币)。

      3. 由于k = monsters[i] - a,所以实际的 gold[i] 更新为 gold[i] = gold[i-1] - (monsters[i] - a - 1)

  4. 结果:最终返回 gold 数组中的最大值,即在与所有怪物战斗后,勇者最多能积累的金币数量。

代码实现

以下为python语言的实现代码,如有需要可以参考。

def solution(a: int, n: int, monsters: list) -> int:
    # write code here
    # 对怪物能力值进行排序
    monsters.sort()
    # 初始化金币数组,长度为 n
    gold = [0] * n
 
    for i in range(n):
        # 如果勇者能力值足够击败当前怪物
        if a >= monsters[i]:
            if i > 0:
                gold[i] = gold[i-1] + 1
            else:
                gold[i] = 1  # 第一个怪物,没有前面的状态可以参考
        # 如果勇者能力值不够,但可以通过花费金币击败
        elif monsters[i] - a <= gold[i-1]:
            # 计算花费金币后的剩余金币数
            gold[i] = gold[i-1] - (monsters[i] - a - 1)
            # 更新勇者能力值
            a = monsters[i]
 
    # 返回最多能积累的金币数量
    return max(gold)

总结

这类题目通过动态规划的方法,可以有效地解决在有限资源下最大化收益的问题。关键步骤包括排序、状态定义和状态转移。在这个问题中,排序使得状态转移更加直观,动态规划数组可以记录每一步的最优解,从而最终找到全局最优解。