zoukankan      html  css  js  c++  java
  • hdu6354 Everything Has Changed (圆的相交弧长)

    题目传送门

    题意:

    用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长(图中的红线部分)。

     

    思路:

    首先判定圆与圆A的关系,这题我们只需要与A内切、相交的圆。

    然后就是求每个圆把圆A切割掉多少周长,增加了多少周长(因为圆A被切割的部分在切割后绝对是内凹的,此时周长是增加的),

    内切的时候直接加上切割圆的周长(如最上面的那个小圆),

    相交的圆部分我采用的方法是用余弦定理

    (A的半径记为R,切割圆半径为r,二者的圆心距离为d,圆心的连线与 圆A和一个交点的夹角为a,则2*d*R*cosa=R*R+d*d-r*r)

    求出夹角a,再用弧长公式l=a*r求出弧长最后进行加减即可。

    来自博客:https://www.cnblogs.com/Dillonh/p/9433714.html

    代码:

    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    typedef pair<ll, ll> pll;
    typedef pair<ll, int> pli;
    typedef pair<int, ll> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    #define lson i<<1
    #define rson i<<1|1
    #define bug printf("*********
    ");
    #define FIN freopen("D://code//in.txt", "r", stdin);
    #define debug(x) cout<<"["<<x<<"]" <<endl;
    #define IO ios::sync_with_stdio(false),cin.tie(0);
    
    const double eps = 1e-8;
    const int mod = 10007;
    const int maxn = 1e6 + 7;
    const double pi = acos(-1);
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f;
    
    typedef struct stu {
        double x,y;
    } point;
    
    double Distance(point a,point b) {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    double Inter(point a,double R,point b,double r) { //变化的周长
        double dis=Distance(a,b);
        double angle1=acos((R*R+dis*dis-r*r)/(2.0*R*dis));
        double angle2=acos((r*r+dis*dis-R*R)/(2.0*r*dis));
        double s=r*angle2*2-R*angle1*2;
        return s;
    }
    
    int t, m, R;
    double x, y, r, ans;
    stu o, p;
    
    int main() {
        //FIN;
        scanf("%d", &t);
        while(t--) {
            scanf("%d%d", &m, &R);
            ans = 2 * pi * R;
            o.x = 0, o.y = 0;
            for(int i = 1; i <= m; i++) {
                scanf("%lf%lf%lf", &x, &y, &r);
                p.x = x, p.y = y;
                double d = Distance(o, p);
                if(d - R - r >= eps) continue; //外离
                if(fabs(R - r) - d > eps) continue; //内离
                if(R == r + d) { //内切
                    ans += 2 * pi * r;
                } else { //相交
                    ans += Inter(o, R, p, r);
                }
            }
            printf("%.12f
    ", ans);
        }
        return 0;
    }
    View Code

    还有另外一个代码:

    #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
  • 相关阅读:
    用 WP7开发包 安装 WP7程序(XAP文件)
    在Windows 2003,XP上安装Windows Phone 7开发工具
    AutoResetEvent实现单并发控制
    .net源码研究(1)HashTable
    聚簇索引(Clustered Index)和非聚簇索引 (Non Clustered Index)
    信号量(semaphore)支持 多并发(n>=1)同步锁
    AtlasControlToolkit应用点滴(一)
    依赖注入dependency injection
    AtlasControlToolkit.CascadingDropDownNameValue自定义用法
    Thread.Join
  • 原文地址:https://www.cnblogs.com/zhgyki/p/10398608.html
Copyright © 2011-2022 走看看