zoukankan      html  css  js  c++  java
  • 计算几何+三分求极值——cf1046I

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

    对卡精度又有了一些心得。。如果是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<<'
    ';
    }
  • 相关阅读:
    常见的行元素与块元素
    [转]SVN服务器部署并实现双机同步及禁止普通用户删除文件
    [转]Axure共享工程Shared Project(二):编辑修改和提交
    如何添加网络打印机
    [转]JSON 转换异常 死循环 There is a cycle in the hierarchy
    比较常用的Properties配置文件的使用方法示例
    解决Tomcat项目重复加载导致pemgen space内存溢出
    怎样批量删除.svn文件
    [转]前端工程师必须掌握的知识点
    Freemarker 使用
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12537469.html
Copyright © 2011-2022 走看看