2 激光和镜子 2
1.5 使用 lgamma 函数计算
gamma 函数定义为 Γn = (n − 1)!,有一个函数lgamma 可以计算gamma 函数的自然
对数,换底之后就是答案了。但是即使用扩展精度浮点数精度也不够,要用四精度浮点
数,在 GCC 中为__float128。但是四精度的数学运算需要特殊的quadmath.h 数学库,
而且在连接时要加上-lquadmath 选项。唯一的方法是把源代码复制到代码中,但是这
样代码就超过长度限制了,需要进行精简。用这种方法的标程,有大约 18KB 长。时间
复杂度是 O(1) 的。
1.6 总结
这题是我的原创题,方法也比较多。但是数据范围可能比较神奇。
主要考察了创新能力和分段打表。
2
激光和镜子
2.1 思路
在这个问题中,我们想要把激光从源点发射到终点。激光可以从水平或竖直方向开
始,并且镜子可以放置在特定位置来改变激光的方向。我们想要放置最少的镜子来到达
终点。
我们可以发现在任何激光的最优路径中,任意一条水平或竖直的直线,激光最多只
会覆盖直线上连续的一段。如果激光覆盖了分离的两段,那么我们可以跳过中间转弯的
部分,并且找到一种更优的路径。
因此,激光最多只能在 2N + 2 条直线上行进————N + 1 条水平直线和 N + 1
条竖直直线,与源点和 N 个可以放镜子的点对应。
于是我们可以把这个问题转化为最短路问题。我们想要到达一条经过终点的水平
或竖直的直线,并且我们从一条经过源点的水平或竖直的直线出发。我们可以在两条直
线间切换,当且仅当这两条直线的交点是给定的 N 个点之一,并且我们想要最小化切
换的次数。
2.2 技巧
由于坐标范围很大,我们需要把坐标离散化后再处理。
另外,由于所有的边权都为 1,可以用bfs 来实现最短路,而不用Dijkstra,而且
时间复杂度更优,最短路部分为 O(N)。排序的常数比Dijkstra 小多了。