美文网首页
凸包(旋转卡壳)

凸包(旋转卡壳)

作者: fo0Old | 来源:发表于2017-03-03 15:53 被阅读0次

计算几何模板

struct ConvexHull
{
    const static int __=1e5+5;

    point ch[__];int n;

    static bool cmp(const point &x,const point &y)
    {
        if(x.x==y.x)
            return x.y<y.y;
        return x.x<y.x;
    }

    point& operator[](int x){return ch[x];}

    void add(point &p,int lim)
    {
        while(n>=lim && ((p-ch[n-1])^(ch[n]-ch[n-1]))>0)
            --n;
        ch[++n].set(p.x,p.y);
    }

    ConvexHull() {clear();}

    void get_ConvexHull(point p[],int np)
    {
        sort(p+1,p+1+np,cmp);
        n=0;
        for(int i=1;i<=np;++i)
            add(p[i],2);
        for(int i=np-1,j=n;i>=1;--i)
            add(p[i],j+1);
        --n;
    }

    //周长(若凸包为直线需要除以2)
    double circumference()
    {
        ch[n+1]=ch[1];
        double res=0.0;
        for(int i=1;i<=n;++i)
            res+=line(ch[i],ch[i+1]).length();
        return res;
    }

    void print()
    {
        for(int i=1;i<=n;++i)
            printf("%.2f %.2f\n",(double)ch[i].x,(double)ch[i].y);
    }

    void clear(){n=0;}
}C;

旋转卡壳:

struct point
{
    ll x,y;
    point(ll x=0,ll y=0):
        x(x),y(y) {}
    friend ll operator*(const point& a,const point& b)
    {
        return a.x*b.y-a.y*b.x;
    }
};

point p[100005],tb[100005];

bool cmp(const point& a,const point& b)
{
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}

double cross(const point& st,const point& fir,const point& sec)
{
    double x1=fir.x-st.x,y1=fir.y-st.y;
    double x2=sec.x-st.x,y2=sec.y-st.y;
    return x1*y2-x2*y1;
}

point xl(const point& a,const point& b)//向量b->a
{
    return point(a.x-b.x,a.y-b.y);
}

int tubao(int n)
{
    sort(p+1,p+n+1,cmp);
    int m=0;
    for(int i=1; i<=n; i++)
    {
        while(m>1 && xl(p[i],tb[m-2])*xl(tb[m-1],tb[m-2])>=0)m--;
        tb[m++]=p[i];
    }
    int temp=m;
    for(int i=n-1; i>=1; i--)
    {
        while(m>temp && xl(p[i],tb[m-2])*xl(tb[m-1],tb[m-2])>=0)m--;
        tb[m++]=p[i];
    }
    if(n>1)m--;
//  for(int i=0;i<m;i++)
//      printf("p: %d %d\n",tb[i].x,tb[i].y);
    return m;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(p,0,sizeof(p));
        memset(tb,0,sizeof(tb));
        for(int i=1; i<=n; i++)
            scanf("%lld%lld",&p[i].x,&p[i].y);
        int m=tubao(n);
        tb[m]=tb[0];
        int x=2;
        ll ans=0;
        for(int i=0; i<=m-1; i++)
        {
            while(cross(tb[x],tb[i],tb[(i+1)%m])<
                  cross(tb[(x+1)%m],tb[i],tb[(i+1)%m]))
                x=(x+1)%m;
            ans=max(ans,(tb[x].x-tb[i].x)*(tb[x].x-tb[i].x)
                    +(tb[x].y-tb[i].y)*(tb[x].y-tb[i].y));
            ans=max(ans,(tb[x].x-tb[(i+1)%m].x)*(tb[x].x-tb[(i+1)%m].x)
                    +(tb[x].y-tb[(i+1)%m].y)*(tb[x].y-tb[(i+1)%m].y));
        }
        printf("%lld\n",ans);
    }
    return 0;
}

题目链接:面积最大的三角形

旋转卡壳:

struct point
{
    ll x,y;
    point(ll x=0,ll y=0):
        x(x),y(y) {}
    friend ll operator*(const point& a,const point& b)
    {
        return a.x*b.y-a.y*b.x;
    }
};

point p[50005],tb[50005];

bool cmp(const point& a,const point& b)
{
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}

double cross(const point& st,const point& fir,const point& sec)
{
    double x1=fir.x-st.x,y1=fir.y-st.y;
    double x2=sec.x-st.x,y2=sec.y-st.y;
    return x1*y2-x2*y1;
}

point xl(const point& a,const point& b)//向量b->a
{
    return point(a.x-b.x,a.y-b.y);
}

int tubao(int n)
{
    sort(p+1,p+n+1,cmp);
    int m=0;
    for(int i=1; i<=n; i++)
    {
        while(m>1 && xl(p[i],tb[m-2])*xl(tb[m-1],tb[m-2])>=0)m--;
        tb[m++]=p[i];
    }
    int temp=m;
    for(int i=n-1; i>=1; i--)
    {
        while(m>temp && xl(p[i],tb[m-2])*xl(tb[m-1],tb[m-2])>=0)m--;
        tb[m++]=p[i];
    }
    if(n>1)m--;
// for(int i=0;i<m;i++)
    //    printf("p: %lld %lld\n",tb[i].x,tb[i].y);
    return m;
}

int main()
{
    int n;
    while(~scanf("%d",&n) && ~n)
    {
        memset(p,0,sizeof(p));
        memset(tb,0,sizeof(tb));
        for(int i=1; i<=n; i++)
            scanf("%lld%lld",&p[i].x,&p[i].y);
        int m=tubao(n);
        tb[m]=tb[0];
        double ans=0;
        int fir=1,sec=2;
        for(int i=0; i<=m-1; i++)
        {
            while(1)
            {
                while(cross(tb[i],tb[fir],tb[sec])<cross(tb[i],tb[fir],tb[(sec+1)%m]))
                    sec=(sec+1)%m;
                while(cross(tb[i],tb[fir],tb[sec])<cross(tb[i],tb[(fir+1)%m],tb[sec]))
                    fir=(fir+1)%m;
                if((cross(tb[i],tb[fir],tb[sec])>=cross(tb[i],tb[(fir+1)%m],tb[sec]))
                &&(cross(tb[i],tb[fir],tb[sec])>=cross(tb[i],tb[fir],tb[(sec+1)%m])))
                    break;
            }
            ans=max(ans,fabs(cross(tb[i],tb[fir],tb[sec]))/2.0);
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

相关文章

  • 凸包(旋转卡壳)

    计算几何模板 旋转卡壳: 题目链接:面积最大的三角形 旋转卡壳:

  • 旋转卡壳(入门)

    旋(xuán)转(zhuàn)卡(qia)壳(qiào) 旋转卡壳可以用于求凸包的直径、宽度,两个不相交凸包间的最...

  • 旋转卡壳(一)

    1 .最小面积外接矩形 类似的,要求得外接矩形,则要求出矩形的宽和高,而高的求法已经知道了,是利用叉积求面积的方法...

  • 凸包

    向量的叉乘就是由该两个向量所组成的平行四边形的面积(x1y2-x2y1).这个凸包不是太懂.先留模板在此这个是水平...

  • 凸包

    凸包最常用的凸包算法是Graham扫描法和Jarvis步进法Graham's Scan法这个算法是由数学大师葛立恒...

  • 凸包

    convexHull 实例

  • 凸包

    逼近多边形是轮廓的高度近似,但是有时候我们希望使用一个多边形的凸包来简化它。凸包跟逼近多边形很像,只不过它是物体最...

  • 28 旋转凸台特征

    旋转凸台特征的基本步骤是先绘制草图,之后再通过特征工具栏的旋转凸台按钮来生成旋转特征,如果是建立实体的话需要封闭的...

  • Python3 趣味系列题8 ------ 凸包动态绘制

    本文介绍利用Graham Scan算法获得凸包(平面凸包),并动态展示凸包的形成过程。下面用比较通俗的语言,介绍下...

  • 算法复习-geometric algo

    convex hull 凸包-video25&video26 凸包算法剖析https://cyw3.github....

网友评论

      本文标题:凸包(旋转卡壳)

      本文链接:https://www.haomeiwen.com/subject/bpkrgttx.html