题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=573

题目:


pdf:https://icpcarchive.ecs.baylor.edu/external/25/2572.pdf

依次给出n个圆的圆心坐标和半径,问最终可以看到多少个圆

解题思路:


比如这个图,最终能看到三个圆(而不是两个圆),n个圆,可以想成每个圆对应一种颜色,所以这个图最终露在外面能看到的有3种颜色。

题目特别指出了一个精度值5e-13,这并非是我们常设的eps(因为题目说了末尾最多12位),这个精度是为了避免出现两个圆的交点是一个点这种情况,若交点是一个点,其实这个点非常非常微小,我们无法判断它对最终答案的贡献。

同时这也说明同一个圆心的圆,半径为r-(5e-13), r, r+(5e-13)的结果是一样的,是等价的。比如eps设1e-13,圆A(c,r),圆A圆弧左侧的点P1(r-(5e-13)),圆弧右侧的点P2(r+(5e-13)),比如在圆A之后出现的圆B和P1或者P2相交,那么这两个圆就是相交的,相交部分不为空。

通过圆两两相交得到每个圆上所有交点对应的极角值,对一个圆上的两个相邻极角对应的点所形成的一段圆弧。最终可见的都是圆弧,两个交点确定两条圆弧,分别在多个圆上,以最先出现的圆为基准,判断它上面的圆是否覆盖了最先出现的圆上的圆弧,如果覆盖,那么另一条圆弧(或者说圆,存在全覆盖的情况)是可见的,做个标记。如何判断圆是否覆盖了一条圆弧呢,可以根据这个圆弧的中点来代替整条圆弧判断,故只需判断上述的P1/P2是否在圆内即可。特判圆无交点的情况。

圆A(c,r1),圆B(c,r2),r1<r2,考虑两种情况,A先放,B后放  和  A后放B先放,结果是不一样的。

ac代码:


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10;
const double eps = 1e-13;//eps用于控制精度,或者更高精度
const double  pi = acos(-1.0);//pi// 点
struct Point//点或向量
{double x, y;Point(double x = 0, double y = 0) :x(x), y(y) {}friend bool operator < (Point a, Point b){return a.x == b.x ? a.y < b.y : a.x < b.x;}
};
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);
}
Vector operator / (Vector a, double p)//向量数除
{return Vector(a.x / p, a.y / p);
}
int dcmp(double x)//精度三态函数(>0,<0,=0)
{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 Cross(Vector a, Vector b)//外积
{return a.x * b.y - a.y * b.x;
}
double Length(Vector a)//模
{return sqrt(Dot(a, a));
}
Vector Rotate(Vector a, double rad)//逆时针旋转rad弧度
{return Vector(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad) + a.y*cos(rad));
}
double Angle(Point a)//极角
{return atan2(a.y, a.x);
}
double Distance(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;bool vis;vector<double> rads;//存极角Circle(Point c = Point(), double r = 0):c(c),r(r){vis = false;rads.clear();}Point point_in(double a)//基于极角求圆上一点坐标{double R = r + 5e-13;return Point(c.x + cos(a)*R, c.y + sin(a)*R);}Point point_out(double a){double R = r - 5e-13;return Point(c.x + cos(a)*R, c.y + sin(a)*R);}
};//两圆交点,在板子上稍作修改
void getCirleCirleIntersection(Circle &C1, Circle &C2)//圆的交点的极角是圆的一个属性,已经和圆绑定到一起了
{double d = Length(C1.c - C2.c);if (dcmp(d) == 0) return ;//圆心重合if (dcmp(C1.r + C2.r - d) < 0) return ;//相离if (dcmp(fabs(C1.r - C2.r) - d) > 0) return ; //内含,圆心不重合double a = Angle(C2.c - C1.c);double da = acos((C1.r*C1.r + d * d - C2.r*C2.r) / (2 * C1.r*d));C1.rads.push_back(a+da);if (dcmp(da)!=0) C1.rads.push_back(a-da);a = Angle(C1.c - C2.c);da = acos((C2.r*C2.r+d*d-C1.r*C1.r)/(2*C2.r*d));C2.rads.push_back(a+da);if(dcmp(da)!=0) C2.rads.push_back(a-da);}
Circle a[110];
int n, ans;
double x, y ,z;
void check(Point p)
{for(int i = n-1; i >= 0; i--){if(dcmp(Distance(p, a[i].c)-a[i].r) <= 0){if(!a[i].vis){a[i].vis = true;ans++;}break;}}
}
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);while(scanf("%d", &n)){ans = 0;if(n==0) break;for(int i = 0; i < n; i++){scanf("%lf %lf %lf", &x, &y, &z);a[i] = Circle{Point(x, y), z};}for(int i = 0; i < n; i++)for(int j = i+1; j < n; j++)getCirleCirleIntersection(a[i],a[j]);for(int i = 0; i < n; i++){if(a[i].rads.size() == 0) // 不和其他圆相交{check(a[i].point_in(0));check(a[i].point_out(0));}else{sort(a[i].rads.begin(), a[i].rads.end());a[i].rads.push_back(a[i].rads[0]);//再加2*pifor(int j = 1; j < a[i].rads.size(); j++){double ang = (a[i].rads[j] + a[i].rads[j - 1]) / 2.0;check(a[i].point_in(ang));check(a[i].point_out(ang));}}}printf("%d\n", ans);}return 0;
}

【LA 2572】Viva Confetti(圆与圆弧覆盖+精度问题)相关推荐

  1. LA 2572 Viva Confetti (Geometry.Circle)

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=problem_st ...

  2. LA 2572 Viva Confetti 离散化 *

    题目地址:https://vjudge.net/problem/UVALive-2572 离散化:把每个圆看成是一段一段弧组成的 每个圆拿出来看一下,先求其上与其他所有圆的交点.每两个交点之间的那段弧 ...

  3. Viva Confetti UVALive - 2572

    Viva Confetti UVALive - 2572 **离散化的思想,将每一个圆都分成一个个小圆弧 const int maxn = 100+10; Point center[maxn]; do ...

  4. ZOJ 1696 Viva Confetti 计算几何

    计算几何:按顺序给n个圆覆盖.问最后能够有几个圆被看见.. . 对每一个圆求和其它圆的交点,每两个交点之间就是可能被看到的圆弧,取圆弧的中点,往外扩展一点或者往里缩一点,从上往下推断有没有圆能够盖住这 ...

  5. POJ 1418 Viva Confetti 题解 《挑战程序设计竞赛》

    为什么80%的码农都做不了架构师?>>>    POJ 1418 Viva Confetti礼花:Confetti 是一些大小不一的彩色圆形纸片,人们在派对上.过节时便抛洒它们以示庆 ...

  6. gen_circle_contour_xld创建圆或圆弧的XLD轮廓

    目录 gen_circle_contour_xld(算子) 描述 参数 gen_circle_contour_xld(算子) gen_circle_contour_xld - 创建圆或圆弧的XLD轮廓 ...

  7. 关于objectArx /CAD二次开发中“绘制点、线、圆、圆弧、多段线、矩形、文字等”

    使用CAD软件绘图时,所有的图元均可由点.线.圆.圆弧.多段线.文字等构成,使用objectArx绘制图元时可调用相应的接口函数,如AcDbLine绘制直线. 1.绘制点 参数:pt(点的位置) Ac ...

  8. Canvas学习:绘制圆和圆弧

    圆和圆弧是图形中基本图形之一,今天我们来了解在Canvas中怎么绘制圆和圆弧.在Canvas中绘制圆和圆弧其实和绘制线段和矩形一样的简单.在Canvas中,CanvasRenderingContext ...

  9. 一般是指用计算机绘制的画面,()一般指用计算机绘制的画面,如直线、圆、圆弧、矩形、任意曲线和图表等。A、图形B、图像C、动画D、图...

    ()一般指用计算机绘制的画面,如直线.圆.圆弧.矩形.任意曲线和图表等.A.图形B.图像C.动画D.图 更多相关问题 minf(X)=x12+3x22一3x1x2+4x1-12x2 电子束焊设备应装置 ...

  10. Viva Confetti UVA - 1308

    思路:由于圆与圆相交的可见部分都是有圆弧组成的,枚举一个圆与其他圆的交点,对两交点所形成的圆弧,去判断该圆弧的中间点是否在其他圆内.若都不在,则证明该圆没有被完全遮住. #include <cs ...

最新文章

  1. python中copy怎么用_python中的拷贝copy模块怎么使用?
  2. 用matlab分析时间响应教程,基于Matlab的多自由度耦合滑移模型的动力响应可靠度分析...
  3. 【easysnmp】python snmp IF-MIB::ifPhysAddress messy code,解析mac地址乱码
  4. Server 2008 Core/服务器核心环境安装SQL 2008 方法
  5. Python 链接汇总
  6. python数据获取手段包括哪些_python开发应用-本地数据获取方法
  7. python 运算及注释
  8. java、c语言、python、c++的不同之处_总结几点C/C++、Java与Python的区别
  9. linux系统怎么样同步时间,Linux系统时间同步
  10. 《那些年啊,那些事——一个程序员的奋斗史》——122
  11. 再次思考 classpath 环境变量 等
  12. Everyting 文件查找工具
  13. 图片自动生成css,CSS Sprites Generator
  14. isilon SMB 控制允许IP访问
  15. 检验图片有没有被 P 过
  16. 阿里云物联网平台测试知识点梳理
  17. 携程航班信息爬取(python)---第一次写博客,不好请别见外!
  18. Spring Boot 实现定时任务
  19. 反对知识霸权 (转)
  20. 华为nova7 pro怎么升级鸿蒙,华为nova7升级到EMUI11,8大功能提升,带来更新体验

热门文章

  1. 一个日志框架的开源,有些不错的创意。
  2. 【MySQL】与【Oracle】
  3. Java——抽象类和接口
  4. python 遍历_python dict 两种遍历方式的比较
  5. redismanager 获取不到yml中的密码_恋爱物语APP:在城市的孤独中,获取真爱密码...
  6. flask与js交互的示例代码_用Python做交互式图形
  7. edittext 点击区域外隐藏输入法
  8. python 相关系数矩阵可视化_python seaborn heatmap可视化相关性矩阵实例
  9. fluentmigrator连接mysql_如何利用FluentMigrator实现数据库迁移
  10. Kotlin教程(五)类型