1 条题解
-
0
「JOI 2014 Final」飞天鼠 题解
问题分析
飞天鼠 JOI 君需要在树之间飞行,飞行过程中高度会下降,还可以在树上爬升或下降。我们需要找到从起点(树 高度 )到终点(树 顶端)的最短时间。
关键约束:
- 飞行时间 秒,高度下降 米
- 飞行后高度必须在 范围内
- 爬升/下降 米需要 秒
核心思路
1. 状态设计与最短路建模
我们使用 Dijkstra 算法求解最短时间,但需要巧妙设计状态。
定义 表示到达树 时,为了能够继续飞行所需要额外爬升的最小总时间。
为什么这样设计?
- 飞行时高度会下降,可能需要在当前树爬升以保证能飞到下一棵树
- 这个定义包含了所有必要的调整时间
2. 状态转移分析
从树 飞到树 需要时间 :
飞行可行性条件:当前高度必须满足:
- 飞行后高度 :(已在建图时处理)
- 飞行后高度 :飞行前高度
关键观察:如果到达 时高度不够,需要先爬升。飞行到 后,如果高度低于 的理想高度,还需要在 处爬升。
状态转移方程:
解释:
- :如果目标树 较矮,需要提前降低飞行高度
- :继承之前的调整时间加上飞行时间
3. 建图策略
只建立可行的飞行边:
if (w <= h[u]) g[u].emplace_back(v, w); // 从u飞到v可行 if (w <= h[v]) g[v].emplace_back(u, w); // 从v飞到u可行4. 最终答案计算
到达树 后,还需要爬到顶端:
简化后:
算法正确性证明
1. 最优子结构
确实表示到达树 时所需的最小调整时间:
- 包含了所有为了满足飞行约束而进行的爬升
- 通过 Dijkstra 可以保证找到全局最优解
2. 状态转移正确性
对于边 :
- 如果 较小,必须提前在之前的树上降低飞行高度
- 如果之前调整时间较长,需要继续累积
- 操作确保满足所有约束条件
3. 最终答案正确性
从 恢复到实际时间:
- 是额外爬升时间
- 还需要从当前高度爬到树顶:
- 总时间 = 调整时间 + 最后爬升时间
复杂度分析
- 建图:
- Dijkstra:
- 总复杂度:
对于 可以接受。
示例验证
样例 1
输入:
5 5 0 50 100 25 30 10 1 2 10 2 5 50 2 4 20 4 3 1 5 4 20执行过程:
- 从树1高度0出发,需要爬升到足够高度
- 通过 Dijkstra 计算最小调整时间
- 最终答案:
路径验证:
- 树1爬升50米:时间50
- 1→2飞行:时间10,高度40→30
- 2→4飞行:时间20,高度30→10
- 4→5飞行:时间20,高度10→-10(不可行!说明需要调整)
- 实际需要提前爬升,最终时间110合理
样例 2
2 1 0 1 1 1 2 100输出:-1(飞行时间100秒,但树高只有1米,无法飞行)
样例 3
4 3 30 50 10 20 50 1 2 10 2 3 10 3 4 10输出:100(需要适当调整飞行高度)
总结
本题的难点在于:
- 飞行高度约束的处理
- 爬升时间与飞行时间的统筹优化
- 状态设计的巧妙性:用调整时间来统一处理所有约束
通过将问题转化为带约束的最短路问题,并使用 Dijkstra 算法求解,我们能够在合理时间内找到最优解。
- 1
信息
- ID
- 5351
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者