1 条题解
-
0
思路与算法
用参数t,u∈[0,1]表示X=A+t(B−A)、Y=C+u(D−C)。时间为|AX|/P+|XY|/R+|YD|/Q。固定t,对u三分求最优;把这个最优值视为t的函数,再外层三分,输出所得时间。零长度线段无需除线段长度,参数表示仍有效。
正确性说明
前后两项是参数的线性函数,中间项是仿射向量的欧氏范数,因此联合目标是凸函数。固定t后的u截面凸,三分保留最小点;在凸集合[0,1]上对u取下确界后,关于t仍凸,外层三分也有效。连续性与紧致区间保证最优值存在,端点最优可由收缩区间逼近。100轮三分后参数区间乘(2/3)^100,路径长度的Lipschitz界由线段长度和最小速度给出,远小于公开误差。
复杂度
初始化O(1),内外各100轮、每次常数次距离,总约O(100²)时间、O(1)空间;若精度参数δ显式计,O(log²(1/δ))。
易错点
三段速度按P、R、Q对应,CD只走Y到D。端点、重合点、零长度线段均合法,不能对线段长度作不安全除法。按题面公开数值误差判定,不把金答案高精度字符串逐字比较。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; using D = long double; struct P { D x, y; }; D dist(P a, P b) { return hypotl(a.x - b.x, a.y - b.y); } P mix(P a, P b, D t) { return {a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t}; } int main() { P A, B, C, Dd; D p, q, r; cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> Dd.x >> Dd.y >> p >> q >> r; auto inner = [&](D t) { P x = mix(A, B, t); auto f = [&](D v) { P y = mix(C, Dd, v); return dist(A, x) / p + dist(x, y) / r + dist(y, Dd) / q; }; D l = 0, h = 1; for (int i = 0; i < 100; i++) { D a = (2 * l + h) / 3, b = (l + 2 * h) / 3; if (f(a) < f(b)) h = b; else l = a; } return f((l + h) / 2); }; D l = 0, h = 1; for (int i = 0; i < 100; i++) { D a = (2 * l + h) / 3, b = (l + 2 * h) / 3; if (inner(a) < inner(b)) h = b; else l = a; } cout << fixed << setprecision(2) << inner((l + h) / 2) << '\n'; }
- 1