枚举所有时刻,在两个时刻之间三分,因为距离肯定是个单峰函数
对卡精度又有了一些心得。。如果是db和某个int标准值比较,那么用sign,如果是两个db判大小,如三分,二分里精度要求高,那么不用sign会比较好
/* 从时间1-n段枚举这个过程 将每个人每个时间段的路程看做是线段, 求出两线段的最近点,如果<=d1且之前结束时间点有距离>=d2,那么ans++ */ #include<bits/stdc++.h> using namespace std; typedef double db; #define N 200005 const db eps=1e-6; const db pi=acos(-1); int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;} int cmp(db k1,db k2){return sign(k1-k2);} int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 struct point{ db x,y; point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} point operator * (db k1) const{return (point){x*k1,y*k1};} point operator / (db k1) const{return (point){x/k1,y/k1};} int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;} db abs(){return sqrt(x*x+y*y);} db abs2(){return x*x+y*y;} db dis(point k1){return ((*this)-k1).abs();} point unit(){db w=abs(); return (point){x/w,y/w};} }; int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);} db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} int intersect(db l1,db r1,db l2,db r2){ if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1; } int checkSS(point k1,point k2,point k3,point k4){ return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&& sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&& sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0; } point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影 point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2()); } db disSP(point k1,point k2,point q){ point k3=proj(k1,k2,q); if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2)); } db disSS(point k1,point k2,point k3,point k4){ if (checkSS(k1,k2,k3,k4)) return 0; else return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2))); } point A[N],B[N]; int n,d1,d2,tot; int main(){ cin>>n>>d1>>d2; for(int i=1;i<=n;i++) cin>>A[i].x>>A[i].y>>B[i].x>>B[i].y; int flag=0; if(sign(A[1].dis(B[1])-d1)<=0)tot++,flag=1; db last=A[1].dis(B[1]); for(int i=2;i<=n;i++){ point Va=A[i]-A[i-1],Vb=B[i]-B[i-1]; db L=0,R=1,mid,midr,ans;//三分求最近距离 while(R-L>eps){ mid=(L+R)/2; midr=(mid+R)/2; db dis1=(A[i-1]+Va*mid).dis(B[i-1]+Vb*mid); db dis2=(A[i-1]+Va*midr).dis(B[i-1]+Vb*midr); if(dis1<dis2) ans=dis1,R=midr; else ans=dis2,L=mid; } if(sign(ans-d1)<=0){ if(flag==0)tot++,flag=1; } last=A[i].dis(B[i]); if(sign(last-d2)>=0)flag=0; } cout<<tot<<' '; }