• P3829 [SHOI2012]信用卡凸包


    传送门

    弧线不好处理,考虑先求出直线的总长

    画个图发现,把直线向内移动 $r$ 以后,所有直线构成了圆心点集的凸包

    然后考虑弧线的长度,容易发现弧线的长度总是圆的周长,大概证明就是直线需要经过弧线才能拐弯

    因为最后拐回来了,所以绕了一圈,那么弧线的弧度总和就是 $2pi$

    然后求所有圆心的凸包加上圆周长就好了

    注意凸包的精度问题,我代码 $eps=1e-12$ 就会 $GG$,$eps=1e-5$ 就好了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef double db;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const db eps=1e-5,pi=acos(-1.0);
    const int N=1e5+7;
    inline int dcmp(db x) { if(fabs(x)<eps) return 0; return x<0 ? -1 : 1; }
    struct Poi {
        db x,y;
        Poi (db a=0,db b=0) { x=a,y=b; }
        inline Poi operator + (const Poi &tmp) const {
            return Poi(x+tmp.x,y+tmp.y);
        }
        inline Poi operator - (const Poi &tmp) const {
            return Poi(x-tmp.x,y-tmp.y);
        }
        inline bool operator < (const Poi &tmp) const {
            return dcmp(x-tmp.x)!=0 ? x<tmp.x : y<tmp.y;
        }
    }P[N],st[N],T[5];
    inline db Cross(Poi A,Poi B) { return A.x*B.y-A.y*B.x; }
    inline db Dot(Poi A,Poi B) { return A.x*B.x+A.y*B.y; }
    inline db Len(Poi A) { return sqrt(Dot(A,A)); }
    inline bool cmp(const Poi &A,const Poi &B) { return dcmp(Cross(A,B))>0|| (dcmp(Cross(A,B))==0&&Len(A)<Len(B) ); }
    inline Poi rotate(Poi A,db a) { return Poi(A.x*cos(a)-A.y*sin(a) , A.x*sin(a)+A.y*cos(a)); }
    int n,tot;
    inline void ins(db x,db y,db a)
    {
        for(int i=1;i<=4;i++)
            P[++tot]=Poi(x,y)+rotate(T[i],a);
    }
    db Tubao()
    {
        int Top=0;
        sort(P+1,P+tot+1);
        for(int i=tot;i>=1;i--) P[i]=P[i]-P[1];
        sort(P+1,P+tot+1,cmp);
        for(int i=1;i<=tot;st[++Top]=P[i],i++)
            while( Top>1 && dcmp(Cross(P[i]-st[Top-1],st[Top]-st[Top-1]))>=0 ) Top--;
        db res=Len(st[Top]-st[1]); for(int i=2;i<=Top;i++) res+=Len(st[i]-st[i-1]);
        return res;
    }
    int main()
    {
        n=read(); db a,b,r,ans;
        scanf("%lf%lf%lf",&a,&b,&r); ans=pi*r*2; a-=r*2,b-=r*2;
        T[1]=Poi(b/2,a/2); T[2]=Poi(b/2,-a/2); T[3]=Poi(-b/2,a/2); T[4]=Poi(-b/2,-a/2);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&a,&b,&r),ins(a,b,r);
        printf("%.2lf
    ",ans+Tubao());
        return 0;
    }
  • 相关阅读:
    Win7 usb无法识别,感叹号,没有盘符
    MVMM 中的ViewModel 实现IsLoading进度条
    菜鸟喜欢的C# 入门认识和添加,修改,删除 文件夹 文件 大全(转)
    (转)windows负载平衡
    关于刷新页面和用法.(转)
    bat文件调用dos命令 (dos淘金)
    flash新闻轮转:图片和链接从数据库读取之我见
    dling 624+and 2100ap && wireless card&wifi
    html与css小技巧
    小型系统数据库安全小结
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11441619.html
Copyright © 2020-2023  润新知