题目描述
原题来自:SCOI 2010
在一个 2 2 2 维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段 A B AB AB 和线段 C D CD CD 。lxhgww 在 A B AB AB 上的移动速度为 P P P ,在 C D CD CD 上的移动速度为 Q Q Q ,在平面上的移动速度 R R R。
现在 lxhgww 想从 A A A 点走到 D D D 点,他想知道最少需要走多长时间。
Solution
三分套三分。其实就是找一条 A A A到 D D D的最优路径,花费的时间最短。假设在 A B AB AB上找一点 X X X,在 C D CD CD上找一点 Y Y Y,那么所有可能的路径都可以描述为 A − > X − > Y − > D A->X->Y->D A−>X−>Y−>D。 X X X和 Y Y Y对应的时间图一定是凸函数,所以可以在 A B AB AB上三分一个点 X X X,然后用这个 X X X去 C D CD CD上找一点 Y Y Y,使得 Y Y Y的选取对于这个 X X X来讲是最优的。
Code
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
#define x first
#define y second
#define eps 1e-6
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
typedef long long ll;
// #define int long long
const int N = 10010;
struct Point
{
double x,y;
Point(){};
Point(double xx, double yy):x(xx),y(yy){};
Point operator / (double a){return Point(x/a,y/a);}
Point operator - (const Point &a){return Point(x-a.x,y-a.y);}
Point operator + (const Point &a){return Point(x+a.x,y+a.y);}
}A,B,C,D;
double P,Q,R;
double dis(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double calc(Point p){
Point l=C, r=D, midl, midr;
double ans1, ans2;
while (abs(dis(l,r))>eps){
Point len = (r-l)/3;
midl = l + len;
midr = r - len;
ans1 = dis(p,midl)/R + dis(midl,D)/Q;
ans2 = dis(p,midr)/R + dis(midr,D)/Q;
if(ans1 < ans2) r = midr;
else l = midl;
}
return dis(l,p)/R + dis(l,D)/Q;
}
void sol() {
cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y >> P >> Q >> R;
Point midl, midr;
double ans1, ans2;
Point l=A, r=B;
while (abs(dis(l,r))>eps){
Point len = (r-l)/3;
midl = l + len;
midr = r - len;
ans1 = calc(midl) + dis(A,midl)/P;
ans2 = calc(midr) + dis(A,midr)/P;
if(ans1 < ans2) r = midr;
else l = midl;
}
printf("%.2lf", dis(A,l)/P + calc(l));
}
int main(){
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
int T_T=1;
// cin >> T_T;
while (T_T--) sol();
return 0;
}