• hdu4667凸包,切线


    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4667

    题意:给n个圆m个三角形,求包住它们所需的最小长度。

    思路:比赛的时候只想到了三角形用凸包围一下,圆不知道怎么处理。暴力一点的方法呢,把圆均分成了2000个整点,然后求凸包,圆弧上的弧线也用折线替代,这样对精度有损,一开始分成1000个点的时候精度就不够,wa掉了,如果圆上的弧线还是算弧长的话,可能还是可以过的。解题报告上说的是求任意两圆的外切线,得到所有切点,三角形顶点和圆的切点,三角形的顶点来求凸包。

    暴力:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=200000;
    const double eps=1e-10;
    const double PI=acos(-1.0);
    struct Point
    {
        double x,y;
        Point(double x=0,double y=0):x(x),y(y) {}
        bool operator < (const Point& a) const
        {
            if(a.x != x) return x < a.x;
            return y < a.y;
        }
    };
    typedef Point Vector;
    Vector operator + (Vector A,Vector B)
    {
        return Vector(A.x+B.x,A.y+B.y);
    }
    Vector operator - (Vector A,Vector B)
    {
        return Vector(A.x-B.x,A.y-B.y);
    }
    Vector operator * (Vector A,double p)
    {
        return Vector(A.x*p,A.y*p);
    }
    int dcmp(double x)
    {
        if(fabs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    bool operator == (const Point& a,const Point& b)
    {
        return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
    }
    double Dot(Vector A,Vector B)
    {
        return A.x*B.x+A.y*B.y;
    }
    double Length(Vector A)
    {
        return sqrt(Dot(A,A));
    }
    double Cross(Vector A,Vector B)
    {
        return A.x*B.y-A.y*B.x;
    }
    double dist(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    int ConvexHull(Point *p,int n,Point *ch)
    {
        sort(p,p+n);
        n=unique(p,p+n)-p;
        int m=0;
        for(int i=0; i<n; i++)
        {
            while(m>1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) <= 0)
                m--;
            ch[m++]=p[i];
        }
        int k=m;
        for(int i=n-2; i>=0; i--)
        {
            while(m>k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) <= 0)
                m--;
            ch[m++]=p[i];
        }
        if(n>1) m--;
        return m;
    }
    
    Point p[maxn],ch[maxn];
    int num=2000;
    int main()
    {
        freopen("1002.in","r",stdin);
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            double x,y,r;
            int cnt=0;
            while(n--)
            {
                scanf("%lf%lf%lf",&x,&y,&r);
                for(int i=0;i<num;i++)
                    p[cnt++]=Point((x+r*cos(2*PI*i/num)),(y+r*sin(2*PI*i/num)));
            }
            while(m--)
            {
                for(int i=0;i<3;i++)
                {
                    scanf("%lf%lf",&x,&y);
                    p[cnt++]=Point(x,y);
                }
            }
            int k=ConvexHull(p,cnt,ch);
            double ans=0;
            for(int i=0;i<k;i++)
               ans+=dist(ch[i],ch[(i+1)%k]);
            printf("%.10lf
    ",ans);
        }
        return 0;
    }
    View Code

     求切点:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<utility>
    using namespace std;
    const int maxn=30000;
    const double eps=1e-10;
    const double PI=acos(-1.0);
    struct Point
    {
        double x,y;
        Point(double x=0,double y=0):x(x),y(y) {}
    };
    typedef Point Vector;
    Vector operator + (Vector A,Vector B)
    {
        return Vector(A.x+B.x,A.y+B.y);
    }
    Vector operator - (Vector A,Vector B)
    {
        return Vector(A.x-B.x,A.y-B.y);
    }
    Vector operator * (Vector A,double p)
    {
        return Vector(A.x*p,A.y*p);
    }
    int dcmp(double x)
    {
        if(fabs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    bool operator == (const Point& a,const Point& b)
    {
        return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
    }
    double Dot(Vector A,Vector B)
    {
        return A.x*B.x+A.y*B.y;
    }
    double Length(Vector A)
    {
        return sqrt(Dot(A,A));
    }
    double Cross(Vector A,Vector B)
    {
        return A.x*B.y-A.y*B.x;
    }
    Vector Rotate(Vector A,double rad)
    {
        return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
    }
    double dist(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    struct Circle
    {
        Point c;
        double r;
        Circle(Point c=Point(0,0),double r=0):c(c),r(r) {}
        Point getpoint(double a)
        {
            return Point(c.x+cos(a)*r,c.y+sin(a)*r);
        }
    }cir[50];
    Point inPoint()
    {
        double x,y;
        scanf("%lf%lf",&x,&y);
        return Point(x,y);
    }
    Circle inCircle()
    {
        double x,y,r;
        scanf("%lf%lf%lf",&x,&y,&r);
        Point p=Point(x,y);
        return Circle(p,r);
    }
    
    Point tri[200];
    int n,m,cnt;
    pair<Point,int> p[maxn];
    
    void cctangent(Circle A,Circle B,int i,int j)
    {
        double d=dist(A.c,B.c);
        double base=atan2(B.c.y-A.c.y,B.c.x-A.c.x);
        double ang=acos((A.r-B.r)/d);
        p[cnt].first=A.getpoint(base+ang);p[cnt++].second=i;
        p[cnt].first=A.getpoint(base-ang);p[cnt++].second=i;
        p[cnt].first=B.getpoint(base+ang);p[cnt++].second=j;
        p[cnt].first=B.getpoint(base-ang);p[cnt++].second=j;
    }
    void pctangent(Point t,Circle C,int i)
    {
        Vector u=C.c-t;
        double d=Length(u);
        double b=acos(C.r/d);
        double a=atan2(t.y-C.c.y,t.x-C.c.x);
        double ang1=a-b,ang2=a+b;
        p[cnt].first=Point(cos(ang1)*C.r,sin(ang1)*C.r)+C.c;p[cnt++].second=i;
        p[cnt].first=Point(cos(ang2)*C.r,sin(ang2)*C.r)+C.c;p[cnt++].second=i;
    }
    void keypoint()
    {
        cnt=0;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                cctangent(cir[i],cir[j],i,j);
        for(int i=0;i<3*m;i++)
            for(int j=0;j<n;j++)
                pctangent(tri[i],cir[j],j);
        for(int i=0;i<3*m;i++)
        {
            p[cnt].first=tri[i];
            p[cnt++].second=-1;
        }
    }
    bool cmp(const pair<Point, int> &p1, const pair<Point, int> &p2) {
        return dcmp(p1.first.y - p2.first.y) == 0 ? p1.first.x < p2.first.x : p1.first.y < p2.first.y;
    }
    int ConvexHull() {
        int top = 0;
        static pair<Point, int> sk[maxn];
        sort(p + 1, p + 1 + cnt, cmp);
        top = 2, sk[1] = p[1], sk[2] = p[2];
        for (int i = 3; i <= cnt; ++i) {
            while (top >= 2 && dcmp(Cross(p[i].first - sk[top - 1].first, sk[top].first - sk[top - 1].first)) >= 0) --top;
            sk[++top] = p[i];
        }
        int ttop = top;
        for (int i = cnt - 1; i >= 1; --i) {
            while (top > ttop && dcmp(Cross(p[i].first - sk[top - 1].first, sk[top].first - sk[top - 1].first)) >= 0) --top;
            sk[++top] = p[i];
        }
        --top;
        for (int i = 0; i < top; ++i) p[i] = sk[i+1];
        return top;
    }
    void solve()
    {
        int h=ConvexHull();
        double ans=0.;
    //    for(int i=0;i<h;i++)
    //        cout<<p[i].first.x<<" "<<p[i].first.y<<" "<<p[i].second<<endl;
        for(int i=0;i<h;i++)
        {
            if(p[i].second != -1 && p[i].second==p[(i+1)%h].second)
            {
                int k=p[i].second;
                Point p1,p2;
                p1=p[i].first-cir[k].c;
                p2=p[(i+1)%h].first-cir[k].c;
                double ang1=atan2(p1.y,p1.x),ang2=atan2(p2.y,p2.x);
                ang2-=ang1;
                if(ang2<0) ang2+=2*PI;//
                ans+=ang2*cir[k].r;
            }
            else ans+=dist(p[i].first,p[(i+1)%h].first);
        }
        printf("%.10lf
    ",ans);
    }
    int main()
    {
        freopen("1002.in","r",stdin);
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=0;i<n;i++)
                cir[i]=inCircle();
            for(int i=0;i<3*m;i++)
                tri[i]=inPoint();
            if(n==1 && m==0)
               printf("%.10lf
    ",2*PI*cir[0].r);
            else
            {
                keypoint();
                solve();
            }
        }
        return 0;
    }
    View Code

    前几组数据的输出和给的标准数据一样,后面8组数据误差挺大的,wa了,不知道为什么。后面再做。

  • 相关阅读:
    由u盘安装Ubuntu引出的事件
    初试Ubuntu
    从error 中学习
    快手一面:牛客:字符串左移
    快手一面:Leetcode:最小栈
    十三、线程池
    十二、windows临界区、其他各种mutex互斥量
    十一、std::async深入
    LeetCode(703):找出数据流中的第K大元素
    LeetCode(1003):检查替换后的字符串
  • 原文地址:https://www.cnblogs.com/54zyq/p/3261351.html
Copyright © 2020-2023  润新知