码迷,mamicode.com
首页 > 其他好文 > 详细

计算几何+三分求极值——cf1046I

时间:2020-03-21 12:47:59      阅读:54      评论:0      收藏:0      [点我收藏+]

标签:point   a*   nbsp   要求   class   his   swap   div   unit   

枚举所有时刻,在两个时刻之间三分,因为距离肯定是个单峰函数

对卡精度又有了一些心得。。如果是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<<\n;
}

 

计算几何+三分求极值——cf1046I

标签:point   a*   nbsp   要求   class   his   swap   div   unit   

原文地址:https://www.cnblogs.com/zsben991126/p/12537469.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!