「题解」洛谷 P2571 [SCOI2010]传送带

题目

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;
}
posted @ 2020-08-25 21:27  yu__xuan  阅读(98)  评论(0编辑  收藏  举报