英雄升级与奖励最大化| 豆包MarsCode AI 刷题

51 阅读3分钟

英雄奖励与最大化

问题描述

在一个游戏中,小W拥有 n 个英雄,每个英雄的初始能力值均为 1。她可以通过升级操作来提升英雄的能力值,最多可以进行 k 次升级。

每次升级操作包含以下步骤:

  1. 选择一个英雄
  2. 选择一个正整数 x
  3. 将该英雄的能力值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,已达到目标值 1,直接获得奖励2
  2. 第四个英雄初始值为 1,选择 x=1 升级一次变为 2,达到目标值2,获得奖励2
  3. 第三个英雄通过三次合理的升级操作 (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)