英雄奖励与最大化
问题描述
在一个游戏中,小W拥有 n 个英雄,每个英雄的初始能力值均为 1。她可以通过升级操作来提升英雄的能力值,最多可以进行 k 次升级。
每次升级操作包含以下步骤:
- 选择一个英雄
- 选择一个正整数
x - 将该英雄的能力值a_i更新为:a_i=a_i+⌊a_i/x⌋ 其中
⌊ ⌋表示向下取整操作
游戏规则:
- 当英雄的能力值首次达到或超过目标值 b_i时,小W可以获得对应的奖励 c_i
- 每个英雄的奖励只能获得一次
- 升级操作的选择是自由的,可以多次选择同一个英雄进行升级
请计算在最多进行 k 次升级操作后,小W能获得的最大奖励总和。
测试样例
样例1:
输入:
n = 4 ,k = 4 ,b = [1, 7, 5, 2] ,c = [2, 6, 5, 2]输出:9解释:可以通过以下操作获得最大奖励:
- 第一个英雄初始值为 1,已达到目标值 1,直接获得奖励2
- 第四个英雄初始值为 1,选择 x=1 升级一次变为 2,达到目标值2,获得奖励2
- 第三个英雄通过三次合理的升级操作 (1->2->4->5) 可达到目标值5,获得奖励5
总奖励为:2 + 2 + 5 = 9
样例2:
输入:
n = 3 ,k = 0 ,b = [3, 5, 2] ,c = [5, 4, 7]输出:0解释:无法进行升级操作,因此无法获得奖励
样例3:
输入:
n = 3 ,k = 3 ,b = [3, 5, 2] ,c = [5, 4, 7]输出:12解释:可以通过以下操作获得最大奖励: 可以通过合理的升级操作使第一个和第三个英雄达到目标值,获得总奖励5 + 7 = 12
题解
ai = ai + ⌊ai/x⌋ 其中x是正整数,也就是x至少得大于等于1
当x大于ai时,那么⌊ai/x⌋就为0了,相当于没升级还浪费了一次升级机会。 当x等于ai时, 那么⌊ai/x⌋就为1了,相当于升级了1能力。 当x小于ai时, 那么⌊ai/x⌋最大可以为ai(相当于能力翻倍了),最小其实是1(由于是下取整)。
我们可以先计算出每个英雄升级到目标能力值最少花多少升级次数。 我们用f(i,target)表示当前能力值为i,升级到目标能力值target的最少升级次数 如果当前能力值翻倍还比目标能力值小的话,那就翻倍,答案为 1 + f(2 * i,target)。 如果翻倍比目标能力值大,那就取x从2开始往上试探,直到升级完的能力值是小于等于target的。 ,答案是1 + f(i + ⌊i/x⌋ ,target)。 这个过程我们还可以用记忆化搜索做一些优化。
此时我们已经算完了每个英雄升级到目标能力值花的最少次数了。 我们只需要在里面选一些,保证开销小于等于k,并且得到的奖励最多就行了。 其实这个就是一个背包问题了。
def comp2(curlevel, target, memo):
if curlevel == target:
return 0
hashv = 31 * curlevel + target
if hashv in memo:
return memo[hashv]
if 2 * curlevel <= target:
memo[hashv] = 1 + comp2(2 * curlevel, target, memo)
else:
o = 2
while o <= curlevel:
if (curlevel + curlevel // o) > target:
o += 1
else:
break
memo[hashv] = 1 + comp2(curlevel + curlevel // o, target, memo)
return memo[hashv]
def bpack(k, weight, value):
n = len(weight)
dp = [[0] * (k + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(k + 1):
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1] if j >= weight[i - 1] else 0)
return dp[n][k]
def solution(n, k, b, c):
memo = {}
times = [comp2(1, b[i], memo) for i in range(n)]
return bpack(k, times, c)
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)