1 条题解
-
0
题目大意
你在玩一个音游,有 个音符依次落下,第 个音符落在位置 。你有两只手,每只手可以覆盖一个长度为 的区间 。游戏开始时两只手都在 位置。
在音符落下的间隙,你可以移动双手,从 移动到 需要耗费 的体力。
求打到所有音符所需的最小体力消耗。
算法思路
核心思想:状态空间动态规划
本题采用状态空间搜索 + 剪枝优化的策略:
- 状态表示:用 表示左手在 、右手在 ,已消耗体力为 的状态
- 状态转移:对于每个音符,如果当前状态无法覆盖该音符,则分别移动左手或右手来覆盖
关键优化
- 可行性剪枝:如果当前手的位置已经能覆盖音符,则直接保留该状态
- 支配关系剪枝:对于两个状态 和 ,如果: 则状态1被状态2支配,可以剔除
算法流程
初始化:now = {(0, 0, 0)} for 每个音符 p: ne = [] for 每个状态 (x, y, c) in now: if (x ≤ p ≤ x+L) 或 (y ≤ p ≤ y+L): 直接保留状态 else: 生成移动左手的新状态 生成移动右手的新状态 now = 对ne进行剪枝后的状态集合 输出 now 中最小代价复杂度分析
- 最坏情况下状态数可能达到
- 但由于 且使用了有效的剪枝策略,实际状态数得到很好控制
- 每个音符处理的时间复杂度为 ,其中 是状态数量
代码实现要点
- 状态表示:使用结构体
Hands{x, y, c} - 移动策略:
- 如果手在音符左边:移动到
- 如果手在音符右边:移动到
- 剪枝方法:通过比较代价和曼哈顿距离来剔除被支配的状态
示例分析
对于样例:
n=4, L=1 p=[6, 3, 7, 1]最优解为 ,移动路径:
- 左手:(花费 )
- 右手:(花费 )
该算法通过维护可能的状态集合,逐步更新并剪枝,最终找到最小代价解。
- 1
信息
- ID
- 4523
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 8
- 已通过
- 1
- 上传者