题目链接
题目分析
在本题中,我们需要解决两个问题:
- 第一个是计算每个英雄达到 能力值时的最少升级次数。
- 第二个是计算最多进行 次升级操作后,能获得的最大奖励总和。
解题思路
对于第一个问题,每次升级的方式为 ,x取值范围为 。 我们可以使用广度优先搜索,计算到每一个能力值的最少升级次数。在计算 时,我们可以直接枚举 ,但此时时间复杂度为 ,可能会超时。可以使用数论分块的方式计算。
数论分块:我们假设 为 15,那么 的取值有哪些呢?可以列举出来:
15 / 1 = 15
15 / 2 = 7
15 / 3 = 5
15 / 4 = 4
15 / 5 = 3
15 / 6 = 2
15 / 7 = 2
15 / 8 = 1
15 / 9 = 1
15 / 10 = 1
15 / 11 = 1
15 / 12 = 1
15 / 13 = 1
15 / 14 = 1
15 / 15 = 1
可以发现有大量重复的值,除去重复的值最多有 个。 计算这些重复的值,可以通过以下代码实现:
l, r = 1, n
while l <= x:
d = x // l
r = x // d
# 此时表示区间 [l,r] 所有的数除 n 的结果为 d
l = r + 1
对于第二个问题,这符合动态规划的01背包模型,即:有 n 个物品,每个物品的重量为 ,价值为 ,现有一个容量为 的背包,从选择若干个,在总重量不超过 的情况下最大化总价值。
动态规划转移方程如下:
可以使用滚动数组的方式优化空间复杂度,注意此时要倒着枚举 来转移状态:
在本问题中,升级次数为重量,奖励为价值。
具体代码实现
以下是 python 的代码实现:
from collections import deque
N = int(1e5)
w = [1e9] * N
def bfs():
"""
使用广度优先搜索(BFS)算法来更新从起点到每个节点的最短距离。
该函数没有返回值,但会修改全局数组w,以存储从起点到每个节点的最短距离。
"""
# 初始化队列q,用于存储待处理的节点及其对应的步数
q = deque()
# 设置起点的步数为0
w[1] = 0
# 将起点及其步数加入队列
q.append((1, 0))
# 当队列不为空时,循环处理队列中的元素
while q:
# 从队列中取出一个节点及其步数
x, y = q.popleft()
# 初始化l和r,用于计算x的除数范围
l, r = 1, 1
# 遍历x的所有除数
while l <= x:
# 计算x除以l的商
d = x // l
# 计算x除以商的值,以确定除数的范围
r = x // d
# 如果x加上商小于N,并且当前步数加1小于已记录的到达x+d的最小步数
if x + d < N and w[x + d] > y + 1:
# 更新到达x+d的最小步数
w[x + d] = y + 1
# 将x+d及其步数加入队列
q.append((x + d, y + 1))
# 更新l为下一个除数范围的起始值
l = r + 1
def solution(n, k, b, c):
"""
参数:
n -- 物品的数量
k -- 背包的容量
b -- 物品的重量列表
c -- 物品的价值列表
返回:
返回背包能装下的最大价值。
"""
# 初始化动态规划数组,长度为背包容量加一
f = [0] * (k + 1)
# 更新物品重量列表
for i in range(n):
b[i] = w[b[i]]
# 使用动态规划填充背包,计算每个容量下的最大价值
for i in range(n):
for j in range(k, b[i] - 1, -1):
# 对于每个物品,选择放入或不放入背包,取价值较大的情况更新动态规划数组
f[j] = max(f[j], f[j - b[i]] + c[i])
# 返回背包最大容量下的最大价值
return f[k]
if __name__ == "__main__":
# Add your test cases here
print(solution(4, 4, [1, 7, 5, 2], [2, 6, 5, 2]) == 9)
print(solution(3, 0, [3, 5, 2], [5, 4, 7]) == 0)
关键步骤和细节
- 首先,我们计算每个英雄达到 能力值时的最少升级次数。
- 使用广度优先搜索,计算到每一个能力值的最少升级次数。
- 使用数论分块的方式计算 的取值。
- 动态规划求解背包问题,计算每个容量下的最大价值。
- 返回背包最大容量下的最大价值。
复杂度分析
- 广度优先搜索的时间复杂度为 ,其中 是升级的次数。
- 对于每个物品,使用数论分块计算 的取值,时间复杂度为 , 其中 是 。
- 对于动态规划求解背包问题,时间复杂度为 ,其中 是物品的数量, 是背包的容量。
- 动态规划需要 的空间来存储每个容量下的最大价值。
总结
本题的关键是理解问题的要求和限制,以及动态规划的求解过程。首先,我们需要计算每个英雄达到 能力值时的最少升级次数,可以使用广度优先搜索来实现,其中结合数论分块来优化转移次数。最后,我们需要使用动态规划求解背包问题,计算每个容量下的最大价值。