这题简直坑上天
一个多边形给出各个顶点一开始位置,从右往左以v速度扫过去,人站在(0,0),现在要到(0,w)去,速度不能超过u,问最小时间
首先,换个参考系,假设多边形不动,人和终点同时获得一个向右的速度v
然后这样想:如果某一时刻让人的速度小于u,那么这个一定可以用一段全速加上一段停止来替换。因此考虑减速是没有意义的,那么人要么全速要么停止
如果全速,人在x方向上有个向右的速度v,在y方向有个向上的速度u,它的轨迹是一条斜率为k=u/v的直线
如果停止,相当于人在x轴上向右滑动
显然应该先停止再运动
那么轨迹应该是这样的
这图一画出来做法显然啊,先看看直接走能不能走,不能走的话因为多边形一定是经过直线y=u/v*x的,而且是连着的一大块,那么一定可以找到一条直线,使得这条直线恰好相切,而且右边的直线都相离。这显然可以二分
至于看看直线有没有穿过内部,看看点是不是都在直线一侧就好了。这里我直接判p[i].y-k*p[i].x-b大于还是小于0而懒得用向量做了
这题真的有毒啊。。eps设成1e-9就T了设成1e-7就A

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<deque> 9 #include<set> 10 #include<map> 11 #include<ctime> 12 #define LL long long 13 #define inf 0x7ffffff 14 #define eps 1e-7 15 using namespace std; 16 inline LL read() 17 { 18 LL x=0,f=1;char ch=getchar(); 19 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 20 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 inline void write(LL a) 24 { 25 if (a<0){printf("-");a=-a;} 26 if (a>=10)write(a/10); 27 putchar(a%10+'0'); 28 } 29 inline void writeln(LL a){write(a);printf(" ");} 30 int n,w,v,u; 31 double l,r,k,b,ans; 32 struct point{int x,y;}p[100010]; 33 inline bool jud(long double k,long double b) 34 { 35 int tota=0,totb=0; 36 for (int i=1;i<=n;i++) 37 { 38 if (k*p[i].x+b-p[i].y<0)tota++; 39 else totb++; 40 if (tota&&totb)return 0; 41 } 42 return 1; 43 } 44 int main() 45 { 46 n=read();w=read();v=read();u=read(); 47 for (int i=1;i<=n;i++) 48 { 49 p[i].x=read(); 50 p[i].y=read(); 51 } 52 k=(double)u/v; 53 if (jud(k,0.0)){printf("%.8lf",(double)w/u);return 0;} 54 l=0;r=1e9; 55 while (r-l>eps) 56 { 57 double mid=(l+r)/2; 58 if (jud(k,(double)-mid/v*u)){ans=(double)w/u+mid/v;r=mid;} 59 else l=mid; 60 } 61 printf("%.8lf ",ans); 62 }