1 条题解
-
0
题目重述
我们有一个 的网格,要从左上角 走到右下角 ,只能向右或向下走。
- 在第 行上走一步(向右)花费 时间。
- 在第 列上走一步(向下)花费 时间。
求最小总时间。
最大 ,直接 DP 会超时。
关键观察
1. 路径的结构
任何一条路径都可以表示为:
- 从 出发,向右走若干步,向下走若干步,交替进行,最终到达 。
- 假设路径在第 这些行上向右走了若干段,在列 上向下走若干段。
2. 费用计算
总时间 = 所有行段花费 + 所有列段花费。
具体来说:
- 如果在第 行上连续向右走了 步,花费 。
- 如果在第 列上连续向下走了 步,花费 。
问题转化
我们可以把路径看作一系列决策:
每次选择是换到下一行(花费当前列的 )还是换到下一列(花费当前行的 )。更抽象地,这个问题等价于:
- 我们要把 次“向下”和 次“向右”合理安排,使得总花费最小。
- 但花费不是固定的,而是依赖于当前所在的行(向右时)或当前所在的列(向下时)。
核心思路
凸壳优化(斜率优化)
考虑一个更简单的思路:
假设我们知道路径在行 上向右走,在列 上向下走。最优路径的性质是:
- 我们只会在 较小的一些行上向右走较多步。
- 只会在 较小的一些列上向下走较多步。
事实上,可以证明:最优路径只会经过 的前缀最小值行和 的前缀最小值列。
换句话说,路径的拐点只出现在 或 的“极小值”位置。
几何解释
把问题看作在二维平面上:
- 从 到 ,每步 花费当前 对应的 ,每步 花费当前 对应的 。
那么总花费可以写成: [ \text{cost} = \sum_{i=1}^{H-1} B_{p_i} + \sum_{j=1}^{W-1} A_{q_j} ] 其中 是路径在列方向上的分布, 是路径在行方向上的分布。
最终算法思想
- 对 数组做单调栈,求出它的前缀最小值序列。
- 对 数组做单调栈,求出它的前缀最小值序列。
- 用双指针法,在两个序列上“行走”,每次选择当前 最小值和 最小值中更小的那个方向前进,并累加花费。
这实际上是一个贪心过程:
始终选择当前行花费 和列花费 中较小的那个方向走一步,直到到达终点。
为什么贪心正确?
因为如果当前 ,那么向右走一步的代价更小,而且不会影响后续向下的代价(因为向下只依赖于列 ,与行无关)。反之同理。
这样我们就在 时间内解决了问题。
总结
这道题的关键是把二维路径问题转化为一维贪心决策:
- 利用“前缀最小值”性质减少候选决策点。
- 通过比较当前行权 和列权 决定移动方向。
- 用单调栈预处理,双指针模拟行走过程。
- 1
信息
- ID
- 3649
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 8
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者