最新华为OD机试
题目描述
小明和朋友们一起玩跳格子游戏,每个格子上有特定的分数 score = [1, -1, -6, 7, -17, 7],
从起点score[0]开始,每次最大的步长为k,请你返回小明跳到终点 score[n-1] 时,能得到的最大得分。
输入描述
第一行输入总的格子数量 n
第二行输入每个格子的分数 score[i]
第三行输入最大跳的步长 k
备注
-
格子的总长度 n 和步长 k 的区间在 [1, 100000]
-
每个格子的分数 score[i] 在 [-10000, 10000] 区间中
输出描述
输出最大得分
示例1
输入
6
1 -1 -6 7 -17 7
2
输出
14
说明
解题思路
在给定的跳格子游戏中,我们使用动态规划方法来计算每个格子可能达到的最大得分。动态规划的核心在于解决子问题并利用这些子问题的解来解决整个问题。
动态规划公式
设 dp[i]
表示到达第 i
个格子时能得到的最大分数,则 dp[i]
可以通过以下方式计算:
dp[i] = max(dp[j]) + score[i] for j in range(max(0, i-k), i)
这里,max(0, i-k)
到 i-1
表示从当前位置 i
往回看,最远可以从 i-k
跳到 i
。如果 k
大于 i
,则从 0 开始。换句话说,dp[i]
是当前格子的分数加上能跳到这个格子的最大分数。
使用双端队列优化
因为 ( k ) 可能非常大,直接计算每个 ( dp[i] ) 需要 ( O(k) ) 的时间复杂度,总的时间复杂度是 ( O(nk) ),这可能非常耗时。为了优化这一过程,我们使用一个双端队列来维护 ( dp ) 值的索引,并且保持队列中的 ( dp ) 值是单调递减的,这样队列的首元素始终是最大值。
通过这种方法,每个元素最多只被队列添加和删除各一次,因此更新 ( dp ) 数组的过程的时间复杂度降低到 ( O(n) )。
Java
import java.util.