学习技能的时间

66 阅读8分钟

问题描述

小U最近沉迷于一款养成类游戏,游戏中的角色拥有三项属性:体力、智力和武力,初始值均为0。随着每天的游戏进展,这些属性会逐步增加。增加情况由一个二维数组 growup 表示,每个元素是一个长度为3的一维数组,分别表示每天的体力、智力和武力增加值。例如,[[1, 1, 2], [2, 2, 1], [2, 1, 2]] 表示第一天体力增加1,智力增加1,武力增加2,第二天分别增加2,2,1,第三天分别增加2,1,2。

在游戏中,玩家可以通过学习新技能来增强角色,但前提是角色的三项属性必须达到技能学习的要求。每个技能的学习要求也用一个二维数组 skill 表示,数组中的每个元素是一个长度为3的一维数组,分别表示学习某个技能所需的最低体力、智力和武力值。

任务是根据 growup 和 skill 数组,计算出玩家在多少天内可以学习每个技能。如果无法满足某个技能的学习要求,则返回 -1

分析

1. 理解问题核心

我们需要根据游戏中角色属性每天的增长情况(由 growup 数组表示)以及每个技能学习所需的属性要求(由 skill 数组表示),来确定玩家经过多少天能够满足学习每个技能的条件。若始终无法满足某技能学习要求,则返回 -1。

2. 明确数据结构及含义

  • growup 数组:这是一个二维数组,其中每个元素又是一个长度为 3 的一维数组。它详细记录了角色在每天游戏进展过程中,体力、智力和武力这三项属性的增加值。例如,growup[0] 表示第一天各项属性的增加值,growup[1] 表示第二天各项属性的增加值,以此类推。
  • skill 数组:同样是二维数组,每个元素为长度为 3 的一维数组。它规定了学习每个技能所需要的最低体力、智力和武力值。也就是说,只有当角色的三项属性分别都达到对应技能所要求的最低值时,才能够学习该技能。

3. 解决思路分析

计算每天结束时角色的属性值

  • 首先,我们需要根据 growup 数组来逐步计算出角色在每一天结束时的体力、智力和武力这三项属性的累计值。可以通过从第一天开始,依次将每天的属性增加值累加到前一天的累计值上,从而得到每一天结束时角色的完整属性状态。

针对每个技能进行判断

  • 对于 skill 数组中的每个技能要求(即每个长度为 3 的一维数组元素),我们要将其与角色每天结束时的属性值进行比较。
  • 从第一天开始,检查角色当天的三项属性值是否满足该技能的学习要求。如果不满足,就继续检查下一天,直到找到满足要求的那一天或者遍历完所有天数(如果始终未满足,则返回 -1)。

记录满足技能学习要求的天数

  • 当发现角色在某一天的属性值满足了某个技能的学习要求时,记录下这一天的天数(注意天数的计数要从 1 开始,因为题目描述的是每天的情况)。这个记录下来的天数就是玩家能够学习该技能所需要的天数。

  • 对 skill 数组中的每个技能都重复上述判断和记录天数的过程,最终得到一个结果列表,其中每个元素对应一个技能,元素的值为学习该技能所需的天数(若无法满足要求则为 -1)。

通过以上分析的步骤,我们就可以根据给定的 growup 数组和 skill 数组,准确地计算出玩家在多少天内可以学习每个技能,完成题目所要求的任务。

代码

def solution(m, n, arrayM, arrayN):  
    result = []  
    
    # Step 1: Calculate cumulative growth for each attribute over days  
    cumulative_growth = [[0, 0, 0]]  # Start with zeros for day 0  
    for growth in arrayM:  
        new_growth = cumulative_growth[-1][0] + growth[0], cumulative_growth[-1][1] + growth[1], cumulative_growth[-1][2] + growth[2]  
        cumulative_growth.append(new_growth)  
    
    # Step 2: For each skill, find the minimum day required to meet the requirements  
    for skill in arrayN:  
        min_days = -1  # Default value if never satisfied  
        for day in range(1, m + 1):  
            if (cumulative_growth[day][0] >= skill[0] and  
                cumulative_growth[day][1] >= skill[1] and  
                cumulative_growth[day][2] >= skill[2]):  
                min_days = day  
                break  # Found the minimum day for this skill  
        
        result.append(min_days)  
    
    return result  

# Test cases  
if __name__ == "__main__":  
    print(  
        solution(  
            3, 3, [[1, 3, 3], [2, 5, 6], [3, 3, 1]], [[1, 1, 1], [4, 5, 5], [7, 7, 7]]  
        )  
        == [1, 3, -1]  
    )  
    print(  
        solution(  
            2, 2, [[2, 4, 1], [3, 1, 2]], [[3, 5, 2], [7, 7, 7]]  
        )  
        == [2, -1]  
    )  
    print(  
        solution(  
            2, 3, [[2, 4, 1], [3, 1, 2]], [[3, 5, 2], [7, 7, 7], [4, 4, 4]]  
        )  
        == [2, -1, -1]  
    )

2. 代码逻辑分析

函数内部变量初始化

  • result = []:创建一个空列表 result,用于存储计算出的学习每个技能所需的天数结果。

步骤一:计算每天结束时角色属性的累计增长值

  • cumulative_growth = [[0, 0, 0]]:初始化一个列表 cumulative_growth,并将其第一个元素设置为 [0, 0, 0],代表第 0 天角色各项属性的初始值均为 0。

  • 通过循环遍历 arrayM

    • for growth in arrayM::对于 arrayM 中的每个表示每天属性增长值的一维数组 growth,执行以下操作。
    • new_growth = cumulative_growth[-1][0] + growth[0], cumulative_growth[-1][1] + growth[1], cumulative_growth[-1][2] + growth[2]:计算当天结束时角色各项属性的新的累计值。这里是将前一天(通过 cumulative_growth[-1] 获取)的各项属性累计值与当天的属性增长值(growth)对应相加,得到当天结束后的新累计值。
    • cumulative_growth.append(new_growth):将计算得到的新累计值添加到 cumulative_growth 列表中,这样 cumulative_growth 列表就逐步记录了角色在每一天结束时的各项属性累计值。

步骤二:针对每个技能,查找满足学习要求的最小天数

  • 通过循环遍历 arrayN

    • for skill in arrayN::对于 arrayN 中的每个表示技能学习要求的一维数组 skill,执行以下操作。

    • min_days = -1:初始化一个变量 min_days 为 -1,这是默认值,表示如果始终无法满足该技能的学习要求,就返回 -1。

    • 通过循环遍历天数:

      • for day in range(1, m + 1)::从第 1 天开始到第 m 天(因为游戏进展天数是 m),依次检查每一天。

      • 在循环内部,通过条件判断来检查当天角色的各项属性累计值是否满足该技能的学习要求:

        • if (cumulative_growth[day][0] >= skill[0] and cumulative_growth[day][1] >= skill[1] and cumulative_growth[day][2] >= skill[2])::如果当天角色的体力、智力、武力累计值分别都不低于该技能学习所需要的相应最低值,那么就找到了满足该技能学习要求的天数。
        • min_days = day:将当前找到的满足要求的天数赋值给 min_days
        • break:一旦找到满足要求的天数,就跳出内层的天数循环,因为我们要找的是满足要求的最小天数。
    • result.append(min_days):将计算得到的学习该技能所需的最小天数(可能是 -1)添加到 result 列表中,这样 result 列表最终就存储了学习每个技能所需的天数结果。

3. 用到的算法

这段代码主要用到了以下两种常见的算法思想:

累计求和算法

在计算每天结束时角色属性的累计增长值部分,通过循环遍历 arrayM,不断将当天的属性增长值累加到前一天的累计值上,从而得到每一天结束时角色的各项属性累计值。这种不断累加的操作就是累计求和算法的体现,它能够有效地根据每天的变化情况计算出整体的累计结果。

线性搜索算法

在针对每个技能查找满足学习要求的最小天数部分,对于每个技能,从第 1 天开始到第 m 天,依次检查每一天角色的各项属性累计值是否满足该技能的学习要求。这种逐个元素(这里是逐个天数)进行检查的方式就是线性搜索算法的体现,它通过顺序遍历的方式来寻找满足特定条件的元素(这里是满足技能学习要求的天数)。虽然线性搜索算法在数据量较大时效率可能相对较低,但对于本题所涉及的相对较小的天数和技能数量范围,是一种简单且有效的解决方式。

综上所述,这段代码通过上述的代码逻辑和所用到的算法,实现了根据角色属性增长情况和技能学习要求计算学习每个技能所需天数的功能,并通过测试用例进行了验证。