【BZOJ1857】【SCOI2010】传送带 [三分]
2017-02-25 11:08
447 查看
传送带
Time Limit: 1 Sec Memory Limit: 64 MB[Submit][Status][Discuss]
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,ROutput
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位Sample Input
0 0 0 100100 0 100 100
2 2 1
Sample Output
136.60HINT
对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10
Main idea
给定平面上的两条线段AB,CD,在AB,CD上移动会有一个特别的速度,在平面上移动会有一个速度,求从点A到点D的最短时间。
Solution
首先发现坐标范围-1000~1000,并且精度要求不高,从此基础上思考。我们先考虑从AB上一个定点O到CD上的距离,发现其中从O到CD的距离是先减小再增大的,我们大胆猜测这道题的答案满足单峰性。然后我们可以用三分(效率为O(log1.5(n)))来实现。
我们现在可以求出一个定点求CD的最短时间,这里用三分实现。然后怎么办呢?
由于AB也是一条线段,我们大胆猜测,可以再在AB上三分一个点,这样就是三分套三分,最后发现其正确性可以证明。
三分方法(这里给出求最小值的方法):在区间1/3处和2/3处各取两个点l,r,如果左段(即L~l)的答案比右段(r~R)的更优,那么由于单峰性(图像类似一个抛物线)可以抹去右段,多次操作使得答案最优。
Code
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<queue> using namespace std; const int ONE=1005; const int MOD=19650827; int n; struct power { double x,y; double AB,CD,PM; friend power operator +(power a,power b) {a.x=a.x+b.x; a.y=a.y+b.y; return a;} friend power operator -(power a,power b) {a.x=a.x-b.x; a.y=a.y-b.y; return a;} }; power A,B,C,D,v; power l1,l2,r1,r2; power a,b; power pass; int get() { int res,Q=1; char c; while( (c=getchar())<48 || c>57) if(c=='-')Q=-1; if(Q) res=c-48; while((c=getchar())>=48 && c<=57) res=res*10+c-48; return res*Q; } double dist(power a,power b) { return (double)sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } double Getdist(power E,power F) { return dist(A,E)/v.AB + dist(E,F)/v.PM + dist(F,D)/v.CD; } double Trivide(power O) { power l=C,r=D,pass,a,b; while(dist(l,r)>0.001) { pass.x=(r.x-l.x)/3.0; pass.y=(r.y-l.y)/3.0; a=l+pass; b=r-pass; if(Getdist(O,a) < Getdist(O,b)) r=b; else l=a; } return Getdist(O,l); } int main() { scanf("%lf %lf %lf %lf",&A.x,&A.y,&B.x,&B.y); scanf("%lf %lf %lf %lf",&C.x,&C.y,&D.x,&D.y); scanf("%lf %lf %lf",&v.AB,&v.CD,&v.PM); power l=A,r=B; while(dist(l,r)>0.001) { pass.x=(r.x-l.x)/3.0; pass.y=(r.y-l.y)/3.0; a=l+pass; b=r-pass; if(Trivide(a) < Trivide(b)) r=b; else l=a; } printf("%.2lf",Trivide(l)); }View Code
相关文章推荐
- bzoj 1857: [Scoi2010]传送带 三分
- Bzoj 1857: [Scoi2010]传送带(三分套三分)
- [BZOJ 1857][SCOI 2010]传送带(三分套三分)
- BZOJ 1857 SCOI 2010 传送带 三分套三分
- 【BZOJ1857】[Scoi2010]传送带【三分套三分】
- bzoj 1857: [Scoi2010]传送带 三分
- bzoj 1857: [Scoi2010]传送带 三分套三分
- bzoj 1857 [SCOI2010]传送带【三分套三分】
- 【BZOJ1857】[Scoi2010]传送带 三分套三分
- bzoj1857 [Scoi2010]传送带 [三分套三分]
- [省选前题目整理][BZOJ 1857][SCOI 2010]传送带(三分套三分)
- [BZOJ1857][Scoi2010]传送带(三分套三分+计算几何)
- BZOJ 1857 [Scoi2010]传送带 三分套三分
- BZOJ 1857 [Scoi2010]传送带 三分
- BZOJ 1857 [Scoi2010]传送带 三分套三分
- 【BZOJ 1857】[Scoi2010]传送带 三分套三分
- bzoj1857: [Scoi2010]传送带(三分套三分)
- BZOJ1857 SCOI2010 传送带 三分套三分
- 【模版】bzoj1857[Scoi2010]传送带 三分套三分
- 【bzoj1857】[Scoi2010]传送带 三分套三分