zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    解题报告 百进制数
    解题报告 Loongint 的夜晚
    解题报告 树形图计数
    解题报告 一元三次方程求解
    解题报告 Loongint 的旅行安排
    解题报告 数字查找
    用C++编写简单绘图语言的词法分析器——程序清单
    C++ 连接 mysql 的一个例子(Visual Studio 2005)
    fedora 8 下JDK 6.0 配置
    IBM DB2 V9 常用命令
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11441619.html
Copyright © 2011-2022 走看看