ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SHOI2012 信用卡凸包

2020-01-23 23:51:28  阅读:274  来源: 互联网

标签:信用卡 const int double eps 凸包 pi SHOI2012


题意:

题目链接
题目大意:
给出n个四角为pi/4的圆弧的类矩形,求它们凸包的周长

思路:

乍看似乎没有思路,但注意到r=0时求的是一个裸的凸包
考虑当r不等于0时,我们先按之前的方法求出凸包周长
然后对于每个拐点求其角度,而后求出这段圆弧长,累加即可。。。

for(int i=1;i<=m;++i)
{
    ans+=(q[i]-q[i+1]).dist();
    double cs=((q[i]-q[i+1])*(q[i+2]-q[i+1]))/(q[i]-q[i+1]).dist()/(q[i+1]-q[i+2]).dist();
        //点乘a*b=|a||b|cos<a,b>(a,b为向量)
    double dg=pi-acos(cs);
    ans+=dg*r;
}

最后提交AC后看了遍题解,发现圆弧累加后的总长度就是一个整圆的周长,直接加就可以了。

for(int i=1;i<=m;++i)
    ans+=(q[i]-q[i+1]).dist();
ans+=2*pi*r;

注意事项:

pi指180度,而不是360度(这种错只有我才犯吧。。。)

code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const double eps=1e-7;
const double pi=3.1415926535898;
int n,m,cnt,per[N<<2];
double a,b,r;
struct point{double x,y;double dist(){return sqrt(x*x+y*y);}}p[N<<2],q[N<<2];
point operator+(point x,point y){return (point){x.x+y.x,x.y+y.y};}
point operator-(point x,point y){return (point){x.x-y.x,x.y-y.y};}
double operator*(point x,point y){return x.x*y.x+x.y*y.y;}
double operator^(point x,point y){return x.x*y.y-x.y*y.x;}
inline double readin(){double x;scanf("%lf",&x);return x;}
inline double lfabs(double x){return x<-eps?-x:x;}
inline point rot(point pp,double dg)
{
    return (point){pp.x*cos(dg)-pp.y*sin(dg),pp.y*cos(dg)+pp.x*sin(dg)};
}
struct cmpfunctor{
    inline bool operator()(int x,int y)
    {
        double dit=(p[x]-p[1])^(p[y]-p[1]);
        if(lfabs(dit)>eps) return dit>eps;
        return (p[x]-p[1]).dist()<(p[y]-p[1]).dist();
    }
};
inline void Graham()
{
    for(int i=2;i<=cnt;++i)
        if(p[i].x-p[1].x<-eps||(lfabs(p[i].x-p[1].x)<eps&&p[i].y-p[1].y<-eps))
            swap(p[1],p[i]);
    for(int i=1;i<=cnt;++i)per[i]=i;
    sort(per+2,per+cnt+1,cmpfunctor());
    q[++m]=p[1];
    for(int i=2;i<=cnt;++i)
    {
        int j=per[i];
        while(m>1&&((p[j]-q[m-1])^(q[m]-q[m-1]))>-eps) --m;
        q[++m]=p[j];
    }
    q[m+1]=q[1];q[m+2]=q[2];
}
inline double C()
{
    double ans=0;
    for(int i=1;i<=m;++i)
        ans+=(q[i]-q[i+1]).dist();
    return ans+2.0*pi*r;
}
int main()
{
    scanf("%d",&n);
    scanf("%lf%lf%lf",&a,&b,&r);
    for(int i=1;i<=n;++i)
    {
        point pt;scanf("%lf%lf",&pt.x,&pt.y);
        point ne=(point){pt.x+b/2.0-r,pt.y+a/2.0-r};
        point nw=(point){pt.x-b/2.0+r,pt.y+a/2.0-r};
        double dg=readin();
        p[++cnt]=rot(ne-pt,dg)+pt;p[++cnt]=rot(nw-pt,dg)+pt;
        point ps=pt+pt-p[cnt];p[++cnt]=ps;
        ps=pt+pt-p[cnt-2];p[++cnt]=ps;
    }
    Graham();
    printf("%.2lf",C());
    return 0;
}

标签:信用卡,const,int,double,eps,凸包,pi,SHOI2012
来源: https://www.cnblogs.com/zmyzmy/p/12231716.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有