题解:小U快乐生活事件快乐值最大化

130 阅读3分钟

题解:小U快乐生活事件快乐值最大化

小U生活事件快乐值最大化 - MarsCode

问题描述

小U喜欢分享她的日常生活。她有n个事件可以选择分享,分享第ii个事件需要花费ti的时间和hi的精力来编辑文章,并能够获得ai的快乐值。小U想知道,在总花费时间不超过T且总花费精力不超过H的前提下,她最多可以获得多少快乐值。

解题思路

  1. 理解问题:我们需要在给定的总时间和总精力的限制下,选择一些事件来最大化快乐值。

  2. 数据结构选择:我们可以使用动态规划来解决这个问题。定义一个二维数组 dp[i][j],表示在总时间为 i 和总精力为 j 的情况下,可以获得的最大快乐值。

  3. 算法步骤

    • 初始化一个二维数组 dp,大小为 (T+1) x (H+1),所有元素初始化为0。
    • 遍历每个事件,对于每个事件,更新 dp 数组。
    • 对于每个事件 (t_i, h_i, a_i),从后向前遍历 dp 数组,更新 dp[i][j] 为 max(dp[i][j], dp[i-t_i][j-h_i] + a_i),前提是 i >= t_i 且 j >= h_i
  4. 返回结果:最终答案就是 dp[T][H]

def solution(n: int, T: int, H: int, t: list, h: list, a: list) -> int:
    # 初始化dp数组,大小为(T+1) x (H+1),所有元素初始化为0
    dp = [[0] * (H + 1) for _ in range(T + 1)]
    
    # 遍历每个事件
    for i in range(n):
        # 从后向前遍历dp数组,更新dp[i][j]
        for time in range(T, t[i] - 1, -1):
            for energy in range(H, h[i] - 1, -1):
                # 更新dp[time][energy]
                dp[time][energy] = max(dp[time][energy], dp[time - t[i]][energy - h[i]] + a[i])
    
    # 返回最终结果
    return dp[T][H]

if __name__ == '__main__':
    print(solution(n = 2, T = 2, H = 2, t = [1, 3], h = [3, 1], a = [3, 4]) == 0)
    print(solution(n = 3, T = 5, H = 5, t = [2, 1, 3], h = [1, 3, 2], a = [10, 7, 8]) == 18)
    print(solution(n = 1, T = 3, H = 3, t = [4], h = [4], a = [5]) == 0)

学习总结

动态规划通过将复杂问题分解为子问题,并存储子问题的解来避免重复计算,从而提高效率。它适用于各种最优化、计数、存在性、序列、背包和矩阵路径等问题。理解动态规划的关键在于定义状态、找到状态转移方程、初始化状态数组、确定计算顺序和返回结果。

动态规划适用的题目类型

  1. 最优化问题

    • 例如,最大值、最小值、最长路径等问题。
    • 本题就是一个典型的最优化问题,需要在给定的时间和精力限制下,最大化快乐值。
  2. 计数问题

    • 例如,计算有多少种方式可以到达某个状态。
    • 例如,计算有多少种方法可以组成某个金额的硬币组合。
  3. 存在性问题

    • 例如,判断是否存在某种状态或路径。
    • 例如,判断是否可以通过某种操作将一个状态转换为另一个状态。
  4. 序列问题

    • 例如,最长递增子序列、最长公共子序列等问题。
    • 这类问题通常涉及序列的子问题分解。
  5. 背包问题

    • 例如,0/1背包问题、完全背包问题、多重背包问题等。
    • 这类问题通常涉及在给定容量限制下,选择物品以最大化或最小化某个值。
  6. 矩阵路径问题

    • 例如,计算从矩阵的左上角到右下角的最短路径。
    • 这类问题通常涉及矩阵中的路径选择。