• hdu6354 /// 圆的相交


    题目大意:

    给定m r 初始圆盘以原点为圆心半径为r

    给定m个圆的圆心(x,y) 半径r 保证m个圆互不相交且不会覆盖圆盘

    用这m个圆来切割初始的圆盘求最后圆盘外围的长度

    求圆与圆盘的交点

    减去圆盘上两点间的周长 加上圆上两点间的周长 判断一下方向

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    #define PI acos(-1)
    #define pb(a) push_back(a)
    #define mem(i,j) memset(i,j,sizeof(i))
    const int N=1e5+5;
    const int MOD=1e9+7;
    const double eps=1e-8;
    
    double add(double a,double b) {
        if(abs(a+b)<eps*(abs(a)+abs(b))) return 0;
        return a+b;
    }
    int dcmp(double x) {
        if(abs(x)<eps) return 0;
        else return x<0 ? -1:1;
    }
    struct P {
        double x,y;
        P(){} P(double _x,double _y):x(_x),y(_y){}
        P operator - (P p) { return P(add(x,-p.x),add(y,-p.y)); }
        P operator + (P p) { return P(add(x,p.x),add(y,p.y)); }
        P operator * (double d) { return P(x*d,y*d); }
        P operator / (double d) { return P(x/d,y/d); }
        double dot (P p) { return add(x*p.x,y*p.y); }
        double det (P p) { return add(x*p.y,-y*p.x); }
        bool operator == (const P& p)const {
            return abs(x-p.x)<eps && abs(y-p.y)<eps; }
        bool operator < (const P& p)const {
            return x<p.x || (x==p.x && y<p.y); }
    };
    struct L {
        P p, v; double ang;
        L(){} L(P _p,P _v):p(_p),v(_v){ ang=atan2(v.y,v.x); }
        P acP(double t) { return p+v*t; }
    };
    struct C {
        P p; double r;
        C(){} C(P _p,double _r):p(_p),r(_r){}
        P acP(double a) { return P(p.x+cos(a)*r,p.y+sin(a)*r); }
        double AL(double ang) { return ang*r; }
    }c;
    // 求向量a的长度
    double lenP(P a) { return sqrt(a.dot(a)); }
    // 求向量v极角
    double angle(P v) { return atan2(v.y,v.x); }
    // 求两向量夹角
    double Angle(P u,P v) { return acos(u.dot(v)/lenP(u)/lenP(v));}
    /* 判断两圆相交
    求圆c1与c2的交点 并用s保存交点
    w记录是外切1还是内切-1
    */
    int insCC(C c1,C c2,vector<P>& s,int* w) {
        double d=lenP(c1.p-c2.p);
        if(abs(d)<eps) {
            if(abs(c1.r-c2.r)<eps) return -1; // 重合
            return 0; // 内含
        }
        if((c1.r+c2.r-d)<-eps) return 0; // 外离
        if(d-abs(c1.r-c2.r)<-eps) return 0; // 内离
    
        (*w)=dcmp(d-c1.r);
        double ang=angle(c2.p-c1.p); // 向量c1c2求极角
        double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
        // c1与交点的向量 与 c1c2 的夹角
        P p1=c1.acP(ang-da), p2=c1.acP(ang+da); // 求得两交点
    
        s.pb(p1);
        if(p1==p2) return 1; // 同一个点
        s.pb(p2); return 2;
    }
    
    int main()
    {
        int t; scanf("%d",&t);
        while(t--) {
            int m; double r;
            scanf("%d%lf",&m,&r);
            c.p.x=c.p.y=0, c.r=r;
            double ans=2.0*PI*c.r;
            while(m--) {
                //printf("%lf
    ",ans);
                C t; scanf("%lf%lf%lf",&t.p.x,&t.p.y,&t.r);
                vector <P> p; p.clear();
                int w, s=insCC(c,t,p,&w);
                if(s==1) {
                    if(w==-1) ans+=2.0*PI*t.r;
                } else if(s==2) {
                    P u=p[0], v=p[1];
                    double ang=Angle(u,v);
                    if(dcmp(u.det(v))<0) ang=2.0*PI-ang;
                    ans-=c.AL(ang); /// 减去圆盘被切的部分周长
                    u=p[0]-t.p, v=p[1]-t.p;
                    ang=Angle(u,v);
                    if(dcmp(u.det(v))>0) ang=2.0*PI-ang;
                    ans+=t.AL(ang); /// 加上切割产生的新边缘
                }
            }
            printf("%.10f
    ",ans);
        }
    
        return 0;
    }
    View Code

    也可以用余弦定理 https://www.cnblogs.com/Dillonh/p/9433714.html

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    #define PI acos(-1)
    #define pb(a) push_back(a)
    #define mem(i,j) memset(i,j,sizeof(i))
    const int N=1e5+5;
    const int MOD=1e9+7;
    const double eps=1e-8;
    
    double add(double a,double b) {
        if(abs(a+b)<eps*(abs(a)+abs(b))) return 0;
        return a+b;
    }
    int dcmp(double x) {
        if(abs(x)<eps) return 0;
        else return x<0 ? -1:1;
    }
    struct P {
        double x,y;
        P(){} P(double _x,double _y):x(_x),y(_y){}
        P operator - (P p) { return P(add(x,-p.x),add(y,-p.y)); }
        P operator + (P p) { return P(add(x,p.x),add(y,p.y)); }
        P operator * (double d) { return P(x*d,y*d); }
        P operator / (double d) { return P(x/d,y/d); }
        double dot (P p) { return add(x*p.x,y*p.y); }
        double det (P p) { return add(x*p.y,-y*p.x); }
        bool operator == (const P& p)const {
            return abs(x-p.x)<eps && abs(y-p.y)<eps; }
        bool operator < (const P& p)const {
            return x<p.x || (x==p.x && y<p.y); }
    };
    struct C {
        P p; double r;
        C(){} C(P _p,double _r):p(_p),r(_r){}
        P acP(double a) { return P(p.x+cos(a)*r,p.y+sin(a)*r); }
        double AL(double ang) { return ang*r; }
    }c;
    // 求向量a的长度
    double lenP(P a) { return sqrt(a.dot(a)); }
    double change(C t) {
        double D=lenP(t.p);
        if(dcmp(c.r-t.r-D)>0) return 0; // 内离
        if(dcmp(c.r-t.r-D)==0) return 2.0*PI*t.r; // 内切
        if(dcmp(c.r+t.r-D)<=0) return 0; // 外离 外切
        double angc=acos((c.r*c.r+D*D-t.r*t.r)/(2.0*c.r*D));
        double angt=acos((t.r*t.r+D*D-c.r*c.r)/(2.0*t.r*D));
        return t.AL(angt*2.0)-c.AL(angc*2.0);
    }
    
    int main()
    {
        int t; scanf("%d",&t);
        while(t--) {
            int m; double r;
            scanf("%d%lf",&m,&r);
            c.p.x=c.p.y=0, c.r=r;
            double ans=2.0*PI*c.r;
            while(m--) {
                C t; scanf("%lf%lf%lf",&t.p.x,&t.p.y,&t.r);
                ans+=change(t);
            }
            printf("%.10f
    ",ans);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    前端JS 4
    前端JS 3
    前端JS 2
    前端JS 1
    JS的知识补丁
    去除inline-block元素间的空隙
    js中“||”和“&&”的高级用法
    WebAPP-1
    Node.js_1
    click和onclick的区别
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10332468.html
Copyright © 2020-2023  润新知