多多读书¶
可以一分钟看一页或者一分钟看两页。书本的每一页都有一定数量的知识: $$ 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
Created: 2024-12-27 23:17:42