计算几何模板整理

太难的比如三维凸包已过滤,估计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\n",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\n",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\n",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)));
}

扫描线当数据结构吧

转载于:https://www.cnblogs.com/hfctf0210/p/10991771.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值