【bzoj1857】[Scoi2010]传送带 三分套三分

题目描述

在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间。

输入

输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By 第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy 第三行是3个整数,分别是P,Q,R

输出

输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位

样例输入

0 0 0 100
100 0 100 100
2 2 1

样例输出

136.60


题解

三分套三分

显然路线是A->AB段上的某个点M->CD段上的某个点N->D。

容易发现,如果固定了点M,那么时间与N的位置的关系是一个单峰函数。并且在N为最优解的情况下,时间与M的位置的关系也是一个单峰函数。

于是三分套三分即可。三分M的位置,然后求最优解的过程中三分N的位置即可。

时间复杂度$O(cnt^2)$

#include <cmath>
#include <cstdio>
struct data
{
	double x , y;
	data() {}
	data(double a , double b) {x = a , y = b;}
	data operator+(data a) {return data(x + a.x , y + a.y);}
	data operator*(int a) {return data(x * a , y * a);}
	data operator/(int a) {return data(x / a , y / a);}
}A , B , C , D;
double P , Q , R;
inline double dis(data a , data b)
{
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double solve(data M)
{
	data l = C , r = D , mid1 , mid2;
	int cnt = 50;
	while(cnt -- )
	{
		mid1 = (l * 2 + r) / 3 , mid2 = (l + r * 2) / 3;
		if(dis(M , mid1) / R + dis(mid1 , D) / Q < dis(M , mid2) / R + dis(mid2 , D) / Q) r = mid2;
		else l = mid1;
	}
	return dis(A , M) / P + dis(M , l) / R + dis(l , D) / Q;
}
int main()
{
	scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf" , &A.x , &A.y , &B.x , &B.y , &C.x , &C.y , &D.x , &D.y , &P , &Q , &R);
	data l = A , r = B , mid1 , mid2;
	int cnt = 50;
	while(cnt -- )
	{
		mid1 = (l * 2 + r) / 3 , mid2 = (l + r * 2) / 3;
		if(solve(mid1) < solve(mid2)) r = mid2;
		else l = mid1;
	}
	printf("%.2lf\n" , solve(l));
	return 0;
}

 

 

posted @ 2017-10-31 14:48  GXZlegend  阅读(349)  评论(0编辑  收藏  举报