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\n",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\n",ans);
    }

    return 0;
}

也可以用余弦定理 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\n",ans);
    }

    return 0;
}

原文地址:https://www.cnblogs.com/zquzjx/p/10332468.html

时间: 2024-11-10 01:08:02

hdu6354 /// 圆的相交的相关文章

判断矩形和圆是否相交

判断矩形和圆是否相交 思路: 方法一:先判断矩形是否在圆内(矩形的四个顶点是否在圆内),若是则不相交,否则再判断圆心到矩形四条边的最短距离(点到线段的最短距离)是否存在小于半径的,若是则相交(认为矩形包括圆是不相交的,已经先排除了). 方法二:圆分平面为四部分, 方法二:圆分平面四部分,不相交的情况分了几种:长方形在圆形上面,长方形在圆形下面,长方形在圆形左边,长方形在圆形右边,长方形在圆形内部,圆形在长方形内部. 方法三:矩形分平面九部分,用矩形的四个边,把空间划分成为9个区域,判定圆心的位置

hdu6354 Everything Has Changed (圆的相交弧长)

题目传送门 题意: 用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长(图中的红线部分). 思路: 首先判定圆与圆A的关系,这题我们只需要与A内切.相交的圆. 然后就是求每个圆把圆A切割掉多少周长,增加了多少周长(因为圆A被切割的部分在切割后绝对是内凹的,此时周长是增加的), 内切的时候直接加上切割圆的周长(如最上面的那个小圆), 相交的圆部分我采用的方法是用余弦定理 (A的半径记为R,切割圆半径为r,二者的圆心距离为d,圆心的连线与 圆A和一个交点的夹角为a,则2

hdu1174(3维射线与圆是否相交)

简单的题意,要注意z2 = h2*0.9-r2 #include <iostream> #include <cmath> #include <vector> #include <string.h> #include <stdlib.h> #include <algorithm> using namespace std; #define MAX_N 110 /*------------------常量区-----------------

Solution 23: 判断矩形和圆是否相交

问题描述 将原题简单化,在二维平面上怎么判断一个矩形(已知四个矩形的角的坐标)和一个圆(已知圆心坐标和半径)是否相交? 解决思路 枚举各种情况.但是有简单的处理方式.如下图(字丑勿怪= =) 程序 比较简单,就忽略了><

Everything Has Changed(HDU6354+圆交+求周长)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6354 题目: 题意:用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长(图中的红线部分). 思路:首先判定圆与圆A的关系,这题我们只需要与A内切.相交的圆.然后就是求每个圆把圆A切割掉多少周长,增加了多少周长(因为圆A被切割的部分在切割后绝对是内凹的,此时周长是增加的),内切的时候直接加上切割圆的周长(如最上面的那个小圆),相交的圆部分我采用的方法是用余弦定理(A的半径

uva 11177(凸多边形和圆的相交)

题意:按顺时针或逆时针顺序给出一个凸n边形的n个点的坐标,然后让一个圆心在(0,0)的圆和凸n边形相交的面积大于等于R,问圆的最小半径. 题解:这题简直坑爹啊,各种细节错误..修修改改了一天,最后看别人题解也还是不懂为什么OnSegment函数要写成那样...明明不能判断点是否在线段上 ╮(╯▽╰)╭ 画画图思路不难想到,把凸n边形的每条边都和圆判断关系,如果是边的两点都在圆内,两条边对应一个三角形的面积,如果一个点在圆外一个在圆内(包括边界),那就是一个三角形加一个扇形,如果两点都在圆外,分两

HDU 3467 (求五个圆相交面积) Song of the Siren

还没开始写题解我就已经内牛满面了,从晚饭搞到现在,WA得我都快哭了呢 题意: 在DotA中,你现在1V5,但是你的英雄有一个半径为r的眩晕技能,已知敌方五个英雄的坐标,问能否将该技能投放到一个合适的位置,使得对面所有敌人都被眩晕,这样你就有机会能够逃脱. 分析: 对于敌方一个英雄来说,如果技能的投放位置距离他不超过r则满足要求,那么如果要眩晕所有的敌人,可行区域就是以五人为中心的半径为r的圆的相交区域. 现在问题就转化为求五个半径相同的圆的相交部分的面积,如果只有一个点则输出该点. 在求交之前,

几何画板验证圆幂定理流程

几何画板不仅可以方便地制作出各种几何图形,而且可以对几何定理进行实质性的验证.圆幂定理是平面几何中的一个定理,是相交弦定理.切割线定理及割线定理(切割线定理推论)的统一.下面将详细介绍几何画板验证圆幂定理课件的制作方法. 圆幂定理:如果交点为P的两条相交直线与圆O相交于A.B与C.D,则PA·PB=PC·PD. 几何画板制作的验证圆幂定理课件模板样图: 从上图中我们可以看出,交点为P的两条与圆O相交的直线AB.CD,在两条直线上分别取点E.F,通过演示可以发现分别拖动点E和点F,AP·BP=CP

NYOJ 1186 心理阴影(两个圆环的相交面积)

心理阴影 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述       自从shanghai reginal后,zkc学长的心理就有了阴影.什么不敢水题,不敢gj,不敢放松...(各种不敢).同样的你们的zsj学长也是这样的.并且他们的心理阴影是一样一样的. 已知一个人的心理阴影为一个环形,那么求你们的zkc学长和zjs学长站在一起的时候的心理阴影的重叠面积. 输入 T组数据 r,R表示是内圆半径和外圆半径. x1,y1 zkc学长站的位置(抽象为一个点) x2,y2