【三分法】 SCOI2010 传送带 LibreOJ - 10017

https://loj.ac/p/10017

题目描述

原题来自: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值