「题解」洛谷 P2571 [SCOI2010]传送带
题目
思路
三分套三分。
直接给结论,不会证明,感性理解一下。
设 \(E\) 是线段 \(AB\) 上的一点,\(F\) 是 \(CD\) 上的一点,所走的一定是 \(A \rightarrow E \rightarrow \rightarrow F \rightarrow D\)。
结论:三分 \(E\) 所在的点,三分 \(F\) 所在的点,也就是说 计算\(E\) 到 \(F\) 加上 \(F\) 到 \(D\) 的时间是个单峰函数, 然后计算总的时间也是个单峰函数。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define eps 1e-8
double ax, ay, bx, by, cx, cy, dx, dy, p, q, r;
double getd(double x1, double y1, double x2, double y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
double f(double x1, double y1, double x2, double y2) {
double t2 = getd(x1, y1, x2, y2) / r;
double t3 =getd(x2, y2, dx, dy) / q;
return t2 + t3;
}
double work(double x, double y) {
double t1 = getd(ax, ay, x, y) / p;
double lx = cx, ly = cy, rx = dx, ry = dy;
while (getd(lx, ly, rx, ry) > eps) {
double lmidx = lx + (rx - lx) / 3.0, lmidy = ly + (ry - ly) / 3.0;
double rmidx = rx - (rx - lx) / 3.0, rmidy = ry - (ry - ly) / 3.0;
double ans1 = f(x, y, lmidx, lmidy), ans2 = f(x, y, rmidx, rmidy);
if (ans2 - ans1 > eps) rx = rmidx, ry = rmidy;
else lx = lmidx, ly = lmidy;
}
return t1 + f(x, y, lx, ly);
}
int main() {
scanf("%lf %lf %lf %lf", &ax, &ay, &bx, &by);
scanf("%lf %lf %lf %lf", &cx, &cy, &dx, &dy);
scanf("%lf %lf %lf", &p, &q, &r);
double lx = ax, ly = ay, rx = bx, ry = by;
while (getd(lx, ly, rx, ry) > eps) {
double lmidx = lx + (rx - lx) / 3.0, lmidy = ly + (ry - ly) / 3.0;
double rmidx = rx - (rx - lx) / 3.0, rmidy = ry - (ry - ly) / 3.0;
//std::cout << lmidx << " " << lmidy << '\n';
//std::cout << rmidx << " " << rmidy << '\n';
double ans1 = work(lmidx, lmidy), ans2 = work(rmidx, rmidy);
//std::cout << ans1 << " " << ans2 << '\n';
if (ans2 - ans1 > eps) rx = rmidx, ry = rmidy;
else lx = lmidx, ly = lmidy;
}
printf("%.2lf", work(lx, ly));
return 0;
}