zoukankan      html  css  js  c++  java
  • 计算几何模板整理

    太难的比如三维凸包已过滤,估计NOI考不了毒瘤计算几何吧,不过还是背些简单的吧。

    二维凸包https://www.luogu.org/problemnew/show/P2742

    #include<bits/stdc++.h>
    using namespace std;
    struct node{double x,y;}p[10001],q[10001];
    int n,top;
    double ans;
    node operator-(node a,node b){return(node){a.x-b.x,a.y-b.y};}
    double dis(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    double cross(node p1,node p2){return p1.x*p2.y-p2.x*p1.y;}
    bool cmp(node a,node b)
    {
        if(!cross(a-p[0],b-p[0]))return dis(a,p[0])<dis(b,p[0]);
        return cross(a-p[0],b-p[0])>0;
    }
    void Graham()
    {
        int k=0;
        for(int i=1;i<n;i++)if(p[i].y<p[k].y||p[i].y==p[k].y&&p[i].x<p[k].x)k=i;
        swap(p[0],p[k]);
        sort(p+1,p+n,cmp);
        q[0]=p[0],q[1]=p[1],q[2]=p[2];
        top=2;
        for(int i=3;i<n;i++)
        {
            while(top&&cross(p[i]-q[top-1],q[top]-q[top-1])>=0)top--;
            q[++top]=p[i];
        }
        q[++top]=p[0];
        for(int i=0;i<top;i++)ans+=dis(q[i],q[i+1]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
        Graham();
        printf("%0.2f",ans);
    }

    旋转卡壳https://www.lydsy.com/JudgeOnline/problem.php?id=1185

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=5e4+7;
    const double eps=1e-8;
    struct point{double x,y;}p[N],q[N],t[5];
    bool operator<(point a,point b){return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;}
    point operator+(point a,point b){return(point){a.x+b.x,a.y+b.y};}
    point operator-(point a,point b){return(point){a.x-b.x,a.y-b.y};}
    point operator*(point a,double b){return (point){a.x*b,a.y*b};}
    double cross(point a,point b){return a.x*b.y-a.y*b.x;}
    double dot(point a,point b){return a.x*b.x+a.y*b.y;}
    double dis(point a){return sqrt(a.x*a.x+a.y*a.y);}
    int n,top;
    double ans=1e18;
    bool cmp(point a,point b)
    {
        double t=cross(a-p[1],b-p[1]);
        if(fabs(t)<eps)return dis(p[1]-a)-dis(p[1]-b)<0;
        return t>0;
    }
    void Graham()
    {
        for(int i=2;i<=n;i++)if(p[i]<p[1])swap(p[i],p[1]);
        sort(p+2,p+n+1,cmp);
        q[top=1]=p[1];
        for(int i=2;i<=n;i++)
        {
            while(top>1&&cross(q[top]-q[top-1],p[i]-q[top])<eps)top--;
            q[++top]=p[i];
        }
        q[0]=q[top];
    }
    void RC()
    {
        int l=1,r=1,p=1;
        double L,R,D,H;
        for(int i=0;i<top;i++)
        {
            D=dis(q[i]-q[i+1]);
            while(cross(q[i+1]-q[i],q[p+1]-q[i])-cross(q[i+1]-q[i],q[p]-q[i])>-eps)p=(p+1)%top;
            while(dot(q[i+1]-q[i],q[r+1]-q[i])-dot(q[i+1]-q[i],q[r]-q[i])>-eps)r=(r+1)%top;
            if(!i)l=r;
            while(dot(q[i+1]-q[i],q[l+1]-q[i])-dot(q[i+1]-q[i],q[l]-q[i])<eps)l=(l+1)%top;
            L=dot(q[i+1]-q[i],q[l]-q[i])/D,R=dot(q[i+1]-q[i],q[r]-q[i])/D;
            H=fabs(cross(q[i+1]-q[i],q[p]-q[i])/D);
            double tmp=(R-L)*H;
            if(tmp<ans)
            {
                ans=tmp;
                t[0]=q[i]+(q[i+1]-q[i])*(R/D);
                t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r]));
                t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0]));
                t[3]=t[2]-(t[1]-t[0]);
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
        Graham();
        RC();
        printf("%.5lf
    ",ans);
        int p=0;
        for(int i=1;i<=3;i++)if(t[i]<t[p])p=i;
        for(int i=0;i<=3;i++)printf("%.5lf %.5lf
    ",t[(i+p)%4].x,t[(i+p)%4].y);
    }

    半平面交https://www.lydsy.com/JudgeOnline/problem.php?id=1038

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1010;
    struct point{double x,y;}p[N],a[N];
    struct line{point a,b;double slop;}l[N],q[N];
    int n,cnt,tot,top;
    double ans=1e18;
    point operator-(point a,point b){return (point){a.x-b.x,a.y-b.y};}
    double operator*(point a,point b){return a.x*b.y-a.y*b.x;}
    bool operator<(line a,line b){return a.slop==b.slop?(a.b-a.a)*(b.b-a.a)>0:a.slop<b.slop;}
    point inter(line a,line b)
    {
        double k1=(b.b-a.a)*(a.b-a.a),k2=(a.b-a.a)*(b.a-a.a),t=k2/(k1+k2);
        return (point){b.a.x+t*(b.b.x-b.a.x),b.a.y+t*(b.b.y-b.a.y)};
    }
    bool judge(line a,line b,line c){return(c.b-c.a)*(inter(a,b)-c.a)<0;}
    void hpi()
    {
        int qs=0,qe=1;
        for(int i=1;i<=cnt;i++)
        {
            if(l[i].slop!=l[i-1].slop)tot++;
            l[tot]=l[i];
        }
        cnt=tot;
        q[0]=l[1],q[1]=l[2];
        for(int i=3;i<=cnt;i++)
        {
            while(qs<qe&&judge(q[qe-1],q[qe],l[i]))qe--;
            while(qs<qe&&judge(q[qs+1],q[qs],l[i]))qs++;
            q[++qe]=l[i];
        }
        while(qs<qe&&judge(q[qe-1],q[qe],q[qs]))qe--;
        while(qs<qe&&judge(q[qs+1],q[qs],q[qe]))qs++;
        tot=0;
        for(int i=qs;i<qe;i++)a[++tot]=inter(q[i],q[i+1]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lf",&p[i].x);
        for(int i=1;i<=n;i++)scanf("%lf",&p[i].y);
        p[0].x=p[1].x,p[0].y=100001;
        p[n+1].x=p[n].x,p[n+1].y=100001;
        for(int i=1;i<=n;i++)l[++cnt].a=p[i-1],l[cnt].b=p[i],l[++cnt].a=p[i],l[cnt].b=p[i+1];
        for(int i=1;i<=cnt;i++)l[i].slop=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
        sort(l+1,l+cnt+1);
        hpi();
        for(int k=1;k<=tot;k++)
        for(int i=1;i<n;i++)
        {
            point t=(point){a[k].x,-1};
            if(a[k].x>=p[i].x&&a[k].x<=p[i+1].x)
            ans=min(ans,a[k].y-inter((line){p[i],p[i+1]},(line){t,a[k]}).y);
        }
        for(int k=1;k<=n;k++)
        for(int i=1;i<tot;i++)
        {
            point t=(point){p[k].x,-1};
            if(p[k].x>=a[i].x&&p[k].x<=a[i+1].x)
            ans=min(ans,inter((line){a[i],a[i+1]},(line){t,p[k]}).y-p[k].y);
        }
        printf("%.3lf",ans);
    }

    凸包的闵可夫斯基和https://www.luogu.org/problemnew/show/P4557

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+9;
    struct point{
        ll x,y;
        point(ll _x=0,ll _y=0):x(_x),y(_y){}
        friend point operator+(const point&a,const point&b){return point(a.x+b.x,a.y+b.y);}
        friend point operator-(const point&a,const point&b){return point(a.x-b.x,a.y-b.y);}
        friend ll operator*(const point &a,const point &b){return a.x*b.y-a.y*b.x;}
        ll dis(){return x*x+y*y;}
    }p[N],p1[N],p2[N],t[N],v1[N],v2[N];
    bool cmp(point a,point b)
    {
        ll ret=(a-t[1])*(b-t[1]);
        if(ret)return ret>0;
        else return(a-t[1]).dis()<(b-t[1]).dis();
    }
    int n,m,Q,top;
    int Graham(point *p,int cnt)
    {
        for(int i=1;i<=cnt;i++)t[i]=p[i];
        for(int i=2;i<=cnt;i++)if(t[i].x<t[1].x||t[i].x==t[1].x&&t[i].y<t[1].y)swap(t[1],t[i]);
        sort(t+2,t+cnt+1,cmp);
        int tp=1;
        for(int i=2;i<=cnt;i++)
        {
            while(tp>=2&&(t[tp]-t[tp-1])*(t[i]-t[tp-1])<=0)tp--;
            t[++tp]=t[i];
        }
        for(int i=1;i<=tp;i++)p[i]=t[i];
        return tp;
    }
    void work()
    {
        for(int i=1;i<=n;i++)v1[i]=p1[i%n+1]-p1[i];
        for(int i=1;i<=m;i++)v2[i]=p2[i%m+1]-p2[i];
        int l1=1,l2=1;
        p[top=1]=p1[1]+p2[1];
        while(l1<=n&&l2<=m)p[++top]=p[top-1]+(v1[l1]*v2[l2]>=0?v1[l1++]:v2[l2++]);
        while(l1<=n)p[++top]=p[top-1]+v1[l1++];
        while(l2<=m)p[++top]=p[top-1]+v2[l2++];
        top=Graham(p,top);
    }
    int inner(point x)
    {
        if((x-p[1])*(p[2]-p[1])>0||(x-p[1])*(p[top]-p[1])<0)return 0;
        int l=2,r=top,pos=l;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if((p[mid]-p[1])*(x-p[1])>=0)pos=mid,l=mid+1;
            else r=mid-1;
        }
        return(p[pos%top+1]-p[pos])*(x-p[pos])>=0;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&Q);
        for(int i=1;i<=n;i++)scanf("%lld%lld",&p1[i].x,&p1[i].y);
        for(int i=1;i<=m;i++)scanf("%lld%lld",&p2[i].x,&p2[i].y),p2[i].x*=-1,p2[i].y*=-1;
        n=Graham(p1,n);m=Graham(p2,m);
        work();
        while(Q--)
        {
            point q;
            scanf("%lld%lld",&q.x,&q.y);
            printf("%d
    ",inner(q));
        }
    }

    simpson积分https://www.lydsy.com/JudgeOnline/problem.php?id=2178

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define Fabs(x) ((x)>0?(x):-(x))
    using namespace std;
    typedef pair<double,double>pii;
    const int N=1007;
    const double pi=acos(-1.0),eps=1e-13,inf=1e100;
    struct point{int x,y;};
    double dis(point a,point b){return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    struct node{
        point p;int r;
        void read(){scanf("%d%d%d",&p.x,&p.y,&r);}
        pii f(double x)
        {
            if(r<=fabs(p.x-x))return pii(0,0);
            double t=sqrt(r*r-(p.x-x)*(p.x-x));
            return pii(p.y-t,p.y+t);
        }
    }a[N];
    bool operator<(node a,node b){return a.p.x<b.p.x;}
    int n,ban[N];
    pii p[N];
    double F(double x)
    {
        double ret=0,lst=-inf;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            p[++cnt]=a[i].f(x);
            if(p[cnt]==pii(0,0))cnt--;
        }
        sort(p+1,p+cnt+1);
        for(int i=1;i<=cnt;i++)
        if(p[i].first>lst)ret+=p[i].second-p[i].first,lst=p[i].second;
        else if(p[i].second>lst)ret+=p[i].second-lst,lst=p[i].second;
        return ret;
    }
    double simpson(double l,double r,double mid,double cl,double cr,double s)
    {
        double fl=F((l+mid)/2),fr=F((mid+r)/2);
        double ret=(r-l)*(cl+cr+4*s)/6,vl=(mid-l)*(cl+s+4*fl)/6,vr=(r-mid)*(cr+s+4*fr)/6;
        if(Fabs(vl+vr-ret)<eps)return ret;
        return simpson(l,mid,(l+mid)/2,cl,s,fl)+simpson(mid,r,(mid+r)/2,s,cr,fr);
    }
    int main()
    {
        scanf("%d",&n);
        double l=inf,r=-inf;
        for(int i=1;i<=n;i++)
        a[i].read(),l=min(l,(double)a[i].p.x-a[i].r),r=max(r,(double)a[i].p.x+a[i].r);
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++)
        if(!ban[i])for(int j=i+1;j<=n;j++)
        if(!ban[j]&&dis(a[i].p,a[j].p)+a[j].r<=a[i].r)ban[j]=1;
        for(int i=1;i<=n;i++)if(ban[i])swap(ban[i],ban[n]),swap(a[i--],a[n--]);
        printf("%.3lf",simpson(l,r,(l+r)/2,0,0,F((l+r)/2)));
    }

    扫描线当数据结构吧

  • 相关阅读:
    JavaScript+IndexedDB实现留言板:客户端存储数据
    怎么限制Google自动调整字体大小
    《互联网时代》告诉我的互联网简史(二)
    《互联网时代》告诉我的互联网简史(一)
    CSS换行:word-wrap、word-break和text-wrap区别
    php中的字符串和正则表达式
    php数组使用小结
    问题:关于一个贴友的js留言板的实现
    问题:关于坛友的一个定时重复显示和隐藏div的实现
    使用union 外加count
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10991771.html
Copyright © 2011-2022 走看看