Skip to content

多多读书

可以一分钟看一页或者一分钟看两页。书本的每一页都有一定数量的知识: $$ book = [a_1,a_2,\cdots,a_n] $$ 如果一分钟看完一页,可以学到所有的知识。如果一分钟看完两页,只能学到两页知识之和的一半。

问:m分钟看完这本书,最多可以学到多少知识?如果看不完输出-1。

动态规划

dp[i][j]表示读完第i页,用了j时间,获得的最大知识

从前往后递推即可,最终我们的答案就是dp[n][m]

def dp_solver(line1, line2):
    n, m = map(int, line1.split())
    a = list(map(int, line2.split()))

    # dp[i][j] 表示读完第 i 页,用了 j 时间,获得的最大知识
    dp = [[-1 for _ in range(m + 1)] for _ in range(n + 1)]
    # 初始状态
    dp[0][0] = 0
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            # 尝试读一页
            if dp[i - 1][j - 1] != -1:
                dp[i][j] = max(
                    dp[i][j], 
                    dp[i - 1][j - 1] + a[i - 1]
                )
            # 尝试读两页
            if i > 1 and dp[i - 2][j - 1] != -1:
                dp[i][j] = max(
                    dp[i][j], 
                    dp[i - 2][j - 1] + (a[i - 2] + a[i - 1]) / 2
                )
    return dp[n][m]

深度优先搜索

def dfs_solver(line1, line2):
    n, m = map(int, line1.split())
    a = list(map(int, line2.split()))

    # 记忆优化
    # mp[(idx, m)] 表示从idx开始读,有m分钟,能获得的最大知识
    mp = {}

    def dfs(idx, m):
        # idx: 下一个要读的页码
        # m: 剩余时间
        if (idx, m) in mp:
            return mp[(idx, m)]
        # 如果剩余时间不够读完
        if n - idx > 2 * m:
            return -1
        # 递归出口
        if idx == n:
            return 0
        ans = 0
        # 读一页
        res = dfs(idx + 1, m - 1)
        if res != -1:
            # 这次读一页,可以读完整本
            ans += res + a[idx]
        # 读两页
        if idx + 1 < n:
            res = dfs(idx + 2, m - 1)
            if res != -1:
                ans2 = res + (a[idx] + a[idx + 1]) / 2
                ans = max(ans, ans2)
        mp[(idx, m)] = ans
        return mp[(idx, m)]

    return dfs(0, m)

Last update: 2025-04-07 18:17:49
Created: 2024-12-27 23:17:42
Was this page helpful?

Comments