1. 程式人生 > >【SCOI2010】【JZOJ4692】傳送帶

【SCOI2010】【JZOJ4692】傳送帶

Description

在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別為線段AB和線段CD。FTD在AB上的移動速度為P,在CD上的移動速度為Q,在平面上的移動速度R。現在FTD想從A點走到D點,他想知道最少需要走多長時間。

Solution

這題我們先假設在AB線段確定了一個點(x,y),那麼(x,y)到CD線段的一個點(x,y)的距離加上(x,y)到D點的時間顯然是呈一個二次函式。於是我們可以在AB線段上列舉一個點,三分CD上的點,然後取最優即可。

但是,這樣可能會超時,我們考慮點A到(x,y)的時間隨著距離增大而增大,這說明這裡的函式是一條直線,那麼顯然(

x,y)也可以三分出來。這樣時間複雜度是O(log23L)L是線段最長距離),所以是很快的。

Code

請自重!

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define eps 0.001
using namespace std;
double sqr(double x) {return
x*x;} double dis(double x,double y,double x1,double y1) { return sqrt(sqr(x-x1)+sqr(y-y1)); } double calc(double z1,double z2,double z3) {return z1*z3/z2;} double ax,ay,bx,by; double cx,cy,dx,dy; int P,Q,R; double ab,cd; double val(double x,double y,double x1,double y1) { return dis(ax,ay,x,y)/P+dis(x,y,x1,y1)/R+dis(dx,dy,x1,y1)/Q; } double
sf(double x,double y) { double l=0,r=dis(cx,cy,dx,dy); double tmp=2147483647; while(l+eps<r) { double p; double lm=l+(r-l)/3; double rm=r-(r-l)/3; double lx,ly; p=calc(lm,cd,fabs(dx-cx)); if(dx<cx) lx=cx-p; else lx=cx+p; p=calc(lm,cd,fabs(dy-cy)); if(dy<cy) ly=cy-p; else ly=cy+p; double rx,ry; p=calc(rm,cd,fabs(dx-cx)); if(dx<cx) rx=cx-p; else rx=cx+p; p=calc(rm,cd,fabs(dy-cy)); if(dy<cy) ry=cy-p; else ry=cy+p; if(val(x,y,lx,ly)<val(x,y,rx,ry)) r=rm,tmp=val(x,y,lx,ly); else l=lm,tmp=val(x,y,rx,ry); } return tmp; } int main() { cin>>ax>>ay>>bx>>by; ab=dis(ax,ay,bx,by); cin>>cx>>cy>>dx>>dy; cd=dis(cx,cy,dx,dy); cin>>P>>Q>>R; double ans=2147483647; double l=0,r=ab; if(ax==bx && ay==by) ans=sf(ax,ay); while(l+eps<r) { double lm=l+(r-l)/3; double rm=r-(r-l)/3; double lx,ly; double p=calc(lm,ab,fabs(bx-ax)); if(bx<ax) lx=ax-p; else lx=ax+p; p=calc(lm,ab,fabs(by-ay)); if(by<ay) ly=ay-p; else ly=ay+p; double rx,ry; p=calc(rm,ab,fabs(bx-ax)); if(bx<ax) rx=ax-p; else rx=ax+p; p=calc(rm,ab,fabs(by-ay)); if(by<ay) ry=ay-p; else ry=ay+p; double t1=sf(lx,ly),t2=sf(rx,ry); if(t1<t2) ans=t1,r=rm; else ans=t2,l=lm; } printf("%.2lf",ans); }