题目大意:

给定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+;
const int MOD=1e9+;
const double eps=1e-; double add(double a,double b) {
if(abs(a+b)<eps*(abs(a)+abs(b))) return ;
return a+b;
}
int dcmp(double x) {
if(abs(x)<eps) return ;
else return x< ? -:;
}
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 -; // 重合
return ; // 内含
}
if((c1.r+c2.r-d)<-eps) return ; // 外离
if(d-abs(c1.r-c2.r)<-eps) return ; // 内离 (*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)/(*c1.r*d));
// c1与交点的向量 与 c1c2 的夹角
P p1=c1.acP(ang-da), p2=c1.acP(ang+da); // 求得两交点 s.pb(p1);
if(p1==p2) return ; // 同一个点
s.pb(p2); return ;
} int main()
{
int t; scanf("%d",&t);
while(t--) {
int m; double r;
scanf("%d%lf",&m,&r);
c.p.x=c.p.y=, 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==) {
if(w==-) ans+=2.0*PI*t.r;
} else if(s==) {
P u=p[], v=p[];
double ang=Angle(u,v);
if(dcmp(u.det(v))<) ang=2.0*PI-ang;
ans-=c.AL(ang); /// 减去圆盘被切的部分周长
u=p[]-t.p, v=p[]-t.p;
ang=Angle(u,v);
if(dcmp(u.det(v))>) ang=2.0*PI-ang;
ans+=t.AL(ang); /// 加上切割产生的新边缘
}
}
printf("%.10f\n",ans);
} return ;
}

也可以用余弦定理 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+;
const int MOD=1e9+;
const double eps=1e-; double add(double a,double b) {
if(abs(a+b)<eps*(abs(a)+abs(b))) return ;
return a+b;
}
int dcmp(double x) {
if(abs(x)<eps) return ;
else return x< ? -:;
}
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)>) return ; // 内离
if(dcmp(c.r-t.r-D)==) return 2.0*PI*t.r; // 内切
if(dcmp(c.r+t.r-D)<=) return ; // 外离 外切
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=, 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 ;
}

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

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

    题目传送门 题意: 用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长(图中的红线部分). 思路: 首先判定圆与圆A的关系,这题我们只需要与A内切.相交的圆. 然后就是求 ...

  2. codeforce gym/100495/problem/K—Wolf and sheep 两圆求相交面积 与 gym/100495/problem/E—Simple sequence思路简述

    之前几乎没写过什么这种几何的计算题.在众多大佬的博客下终于记起来了当时的公式.嘚赶快补计算几何和概率论的坑了... 这题的要求,在对两圆相交的板子略做修改后,很容易实现.这里直接给出代码.重点的部分有 ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6354 题目: 题意:用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长( ...

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

    简单的题意,要注意z2 = h2*0.9-r2 #include <iostream> #include <cmath> #include <vector> #in ...

  5. 多边形和圆的相交面积(模板)hdu2892、hdu4404

    area Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

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

    还没开始写题解我就已经内牛满面了,从晚饭搞到现在,WA得我都快哭了呢 题意: 在DotA中,你现在1V5,但是你的英雄有一个半径为r的眩晕技能,已知敌方五个英雄的坐标,问能否将该技能投放到一个合适的位 ...

  7. HDU 3264 Open-air shopping malls (计算几何-圆相交面积)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3264 题意:给你n个圆,坐标和半径,然后要在这n个圆的圆心画一个大圆,大圆与这n个圆相交的面积必须大于等 ...

  8. CodeForces 8D Two Friends 判断三个圆相交

    题意: 有两个人\(Alan\)和\(Bob\),他们现在都在\(A\)点,现在\(Bob\)想去\(B\)点,\(Alan\)想先到\(C\)点再去\(B\)点. \(Alan\)所走的总路程不能超 ...

  9. hdu5858 Hard problem(求两圆相交面积)

    题目传送门 Hard problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

随机推荐

  1. Java.io包

    Java.io.BufferedInputStream 类添加功能到另一个输入流,缓冲输入以及支持mark和reset methods.Following是关于缓冲输入流的要点: 当创建缓冲输入,创建 ...

  2. 树莓派上Opencv highgui的问题

    错误描述:https://bbs.csdn.net/topics/394616975?page=1#post-409508178 解决方案:直接改系统环境变量 # vim /etc/profile e ...

  3. LeetCode Array Easy 1. Two Sum

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  4. shell read变量

  5. Python大小写转换

    大小写转换 name = "xiao ming" name = name.upper() # 转为大写 print(name) name = name.lower() # 转为小写 ...

  6. shell script test指令的测试功能 &和&&,|和|| 区别 变量名赋值=号前后的空格问题(天坑)

    小程序告一段落,达到阶段性目标.下一步继续Linux的学习....脑子不够用啊...真费... 书中介绍..检测系统某些文件或者相关属性时,用test指令.. 例如.测试某个文档目录是否存在可以  t ...

  7. 前端学习(三)css选择器(笔记)

    字体样式:    color:red:    font-size:12px:    font-weight:bold/normal;    font-style:italic/normal;    f ...

  8. 前后端分离进行权限管理之后端API返回菜单及权限信息(三)

    一.动态菜单API的生成 1.API #菜单信息 url(r'^menus$', views.MenuModelView.as_view({"get": "list&qu ...

  9. python 操作redis数据

    python 操作redis 各种类型的数据 # encoding:utf-8 import redis import time def main(): """ redi ...

  10. SQL 在表中插入

    SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL INSERT INTO 语句 INSERT INTO 语句用于向表中插入新记录. SQL ...