【BZOJ】1857: [Scoi2010]传送带(三分)

http://www.lydsy.com/JudgeOnline/problem.php?id=1857

好神奇的三分。。

第一次写三分啊sad。。看了题解啊题解QAQ

首先发现无论怎么走一定是在AB和CD上选了两个点然后走的(包括ABCD四个点),所以我们就是要找出这两个点就行了。

且AB上有且只有一个最优点,而每一个AB上的点也对应CD唯一一个最优点orz。

所以我们三分AB上的点(酷炫但是不知道为啥这是个单峰函数orz),然后对应三分CD上的点(这个比前面的好证。。这个初中就学了的吧。sad)然后就行了。。

距离和费用就是三段的和。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }

const double eps=1e-3;
int ax, ay, bx, by, cx, cy, dx, dy;
double P, Q, R;
double dis(double x1, double y1, double x2, double y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); }
double cal(double x, double y) {
	double x1, x2, y1, y2, lx=cx, ly=cy, rx=dx, ry=dy;
	while(abs(rx-lx)>eps || abs(ry-ly)>eps) {
		x1=lx+(rx-lx)/3;	y1=ly+(ry-ly)/3;
		x2=lx+(rx-lx)/3*2;	y2=ly+(ry-ly)/3*2;
		double d1=dis(x1, y1, x, y)/R+dis(x1, y1, dx, dy)/Q;
		double d2=dis(x2, y2, x, y)/R+dis(x2, y2, dx, dy)/Q;
		if(d1<d2) rx=x2, ry=y2;
		else lx=x1, ly=y1;
	}
	return dis(x, y, ax, ay)/P+dis(lx, ly, x, y)/R+dis(lx, ly, dx, dy)/Q;
}
int main() {
	cin >> ax >> ay >> bx >> by >> cx >> cy >> dx >> dy >> P >> Q >> R;
	double x1, x2, y1, y2, lx=ax, ly=ay, rx=bx, ry=by;
	while(abs(rx-lx)>eps || abs(ry-ly)>eps) {
		x1=lx+(rx-lx)/3;	y1=ly+(ry-ly)/3;
		x2=rx-(rx-lx)/3;	y2=ry-(ry-ly)/3;
		double d1=cal(x1, y1), d2=cal(x2, y2);
		if(d1<d2) rx=x2, ry=y2;
		else lx=x1, ly=y1;
	}
	printf("%.2lf", cal(lx, ly));
	return 0;
}

Description

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

Input

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

Output

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

Sample Input

0 0 0 100
100 0 100 100
2 2 1


Sample Output

136.60

HINT

对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10

Source

原文地址:https://www.cnblogs.com/iwtwiioi/p/4006866.html