问题描述
小F正在设计一款手游,游戏中的角色战力值需要根据一定规则来平衡,以提升玩家的游戏体验。现在游戏中有 n 个角色,编号从 0 到 n-1。为了保证平衡性,角色战力值需要遵循以下规则:
- 编号为
0的角色战力值初始为0。 - 每个角色的战力值必须是非负整数。
- 相邻角色的战力值差不能超过
1,即两个相邻角色的战力值差可以是0、+1或-1。
除此之外,游戏策划还为某些角色设定了最大战力值。这些限制通过若干数对给出,每一个数对 limit[i] = [index, maxPower],表示编号为 index 的角色的战力值不能超过 maxPower。这些限定只会对编号不为 0 的角色生效。
你的任务是根据上述规则和限制,计算游戏中单个角色能达到的最大战力值。 为了解决这个问题,我们可以使用动态规划(Dynamic Programming, DP)的方法。由于我们需要找到单个角色能达到的最大战力值,并且这个值受到相邻角色战力值差和某些角色的最大战力值限制的影响,因此我们可以定义一个DP数组来记录每个角色在满足所有限制条件下能达到的最大战力值。
具体步骤如下:
-
初始化DP数组:创建一个长度为n的DP数组,其中dp[i]表示编号为i的角色能达到的最大战力值。由于编号为0的角色战力值初始为0,所以dp[0] = 0。
-
处理限制条件:遍历limit数组,更新DP数组中对应角色的最大战力值限制。即对于每个limit[i] = [index, maxPower],将dp[index]的值更新为不超过maxPower的最小值(但这里需要注意,由于我们是从左到右遍历的,所以实际上我们会在后面的DP转移过程中考虑这个限制,而不是直接在这里修改dp[index]的值,因为直接修改可能会影响到后续其他角色的计算)。然而,为了简化处理,我们可以在后续DP转移时检查这个限制。
-
DP转移:从左到右遍历每个角色(除了编号为0的角色,因为它的战力值已知为0),根据相邻角色战力值差不能超过1的限制,更新DP数组。对于每个角色i(i > 0),它的最大战力值dp[i]可以由前一个角色的最大战力值dp[i-1]加1、减1或保持不变得到,但需要满足以下条件:
- dp[i]不能小于0(因为战力值是非负整数)。
- 如果存在对角色i的战力值限制(即limit数组中包含了关于角色i的限制),则dp[i]不能超过该限制。
-
返回结果:遍历完所有角色后,dp数组中的最大值即为单个角色能达到的最大战力值。但是,由于我们是从左到右遍历的,并且每个角色的最大战力值都是基于前一个角色的最大战力值计算得到的,所以实际上dp数组的最后一个元素dp[n-1]并不一定是整个游戏中单个角色能达到的最大战力值(它只表示了编号为n-1的角色能达到的最大战力值)。因此,我们需要遍历整个dp数组,找到其中的最大值作为结果返回。
然而,在这个特定问题中,由于我们是从左到右依次计算每个角色的最大战力值的,并且每个角色的最大战力值都受到前一个角色最大战力值和自身限制条件的影响,所以实际上我们只需要记录到目前为止计算出的最大战力值即可(这个最大值会在遍历过程中不断更新)。在遍历完所有角色后,这个最大值就是我们要找的结果。
下面是实现这个算法的Python代码:
python复制代码
def maxPower(n, m, limit):
# 初始化DP数组,dp[i]表示编号为i的角色能达到的最大战力值
dp = [0] * n
# 将limit数组转换为字典形式,方便后续查找
limits = {index: maxPower for index, maxPower in limit}
# 从左到右遍历每个角色,计算最大战力值
for i in range(1, n):
# 初始化当前角色的最大战力值为前一个角色的最大战力值(加1、减1或保持不变)
dp[i] = max(0, dp[i-1] - 1, dp[i-1] + 1)
# 如果存在对当前角色的战力值限制,则更新最大战力值
if i in limits:
dp[i] = min(dp[i], limits[i])
# 更新到目前为止计算出的最大战力值(这个值会在遍历过程中不断更新)
# 注意:这里其实不需要一个额外的变量来记录这个最大值,因为最后我们只需要返回dp数组中的最大值即可
# 但为了保持代码的清晰性,我还是保留了这一步(在实际实现中可以省略)
# 返回dp数组中的最大值作为结果
return max(dp)
# 测试样例
print(maxPower(3, 2, [[1, 3], [2, 2]])) # 输出: 2
print(maxPower(5, 3, [[1, 1], [2, 3], [4, 3]])) # 输出: 3
print(maxPower(4, 1, [[2, 2]])) # 输出: 3
注意:在上面的代码中,我保留了一个更新到目前为止计算出的最大战力值的步骤(用注释标记了),但实际上这个步骤是多余的,因为我们最终只需要返回dp数组中的最大值即可。因此,在实际实现中,你可以省略这个步骤来简化代码。