【LA 2572】Viva Confetti(圆与圆弧覆盖+精度问题)
题目地址: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(圆与圆弧覆盖+精度问题)相关推荐
- LA 2572 Viva Confetti (Geometry.Circle)
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=problem_st ...
- LA 2572 Viva Confetti 离散化 *
题目地址:https://vjudge.net/problem/UVALive-2572 离散化:把每个圆看成是一段一段弧组成的 每个圆拿出来看一下,先求其上与其他所有圆的交点.每两个交点之间的那段弧 ...
- Viva Confetti UVALive - 2572
Viva Confetti UVALive - 2572 **离散化的思想,将每一个圆都分成一个个小圆弧 const int maxn = 100+10; Point center[maxn]; do ...
- ZOJ 1696 Viva Confetti 计算几何
计算几何:按顺序给n个圆覆盖.问最后能够有几个圆被看见.. . 对每一个圆求和其它圆的交点,每两个交点之间就是可能被看到的圆弧,取圆弧的中点,往外扩展一点或者往里缩一点,从上往下推断有没有圆能够盖住这 ...
- POJ 1418 Viva Confetti 题解 《挑战程序设计竞赛》
为什么80%的码农都做不了架构师?>>> POJ 1418 Viva Confetti礼花:Confetti 是一些大小不一的彩色圆形纸片,人们在派对上.过节时便抛洒它们以示庆 ...
- gen_circle_contour_xld创建圆或圆弧的XLD轮廓
目录 gen_circle_contour_xld(算子) 描述 参数 gen_circle_contour_xld(算子) gen_circle_contour_xld - 创建圆或圆弧的XLD轮廓 ...
- 关于objectArx /CAD二次开发中“绘制点、线、圆、圆弧、多段线、矩形、文字等”
使用CAD软件绘图时,所有的图元均可由点.线.圆.圆弧.多段线.文字等构成,使用objectArx绘制图元时可调用相应的接口函数,如AcDbLine绘制直线. 1.绘制点 参数:pt(点的位置) Ac ...
- Canvas学习:绘制圆和圆弧
圆和圆弧是图形中基本图形之一,今天我们来了解在Canvas中怎么绘制圆和圆弧.在Canvas中绘制圆和圆弧其实和绘制线段和矩形一样的简单.在Canvas中,CanvasRenderingContext ...
- 一般是指用计算机绘制的画面,()一般指用计算机绘制的画面,如直线、圆、圆弧、矩形、任意曲线和图表等。A、图形B、图像C、动画D、图...
()一般指用计算机绘制的画面,如直线.圆.圆弧.矩形.任意曲线和图表等.A.图形B.图像C.动画D.图 更多相关问题 minf(X)=x12+3x22一3x1x2+4x1-12x2 电子束焊设备应装置 ...
- Viva Confetti UVA - 1308
思路:由于圆与圆相交的可见部分都是有圆弧组成的,枚举一个圆与其他圆的交点,对两交点所形成的圆弧,去判断该圆弧的中间点是否在其他圆内.若都不在,则证明该圆没有被完全遮住. #include <cs ...
最新文章
- python中copy怎么用_python中的拷贝copy模块怎么使用?
- 用matlab分析时间响应教程,基于Matlab的多自由度耦合滑移模型的动力响应可靠度分析...
- 【easysnmp】python snmp IF-MIB::ifPhysAddress messy code,解析mac地址乱码
- Server 2008 Core/服务器核心环境安装SQL 2008 方法
- Python 链接汇总
- python数据获取手段包括哪些_python开发应用-本地数据获取方法
- python 运算及注释
- java、c语言、python、c++的不同之处_总结几点C/C++、Java与Python的区别
- linux系统怎么样同步时间,Linux系统时间同步
- 《那些年啊,那些事——一个程序员的奋斗史》——122
- 再次思考 classpath 环境变量 等
- Everyting 文件查找工具
- 图片自动生成css,CSS Sprites Generator
- isilon SMB 控制允许IP访问
- 检验图片有没有被 P 过
- 阿里云物联网平台测试知识点梳理
- 携程航班信息爬取(python)---第一次写博客,不好请别见外!
- Spring Boot 实现定时任务
- 反对知识霸权 (转)
- 华为nova7 pro怎么升级鸿蒙,华为nova7升级到EMUI11,8大功能提升,带来更新体验
热门文章
- 一个日志框架的开源,有些不错的创意。
- 【MySQL】与【Oracle】
- Java——抽象类和接口
- python 遍历_python dict 两种遍历方式的比较
- redismanager 获取不到yml中的密码_恋爱物语APP:在城市的孤独中,获取真爱密码...
- flask与js交互的示例代码_用Python做交互式图形
- edittext 点击区域外隐藏输入法
- python 相关系数矩阵可视化_python seaborn heatmap可视化相关性矩阵实例
- fluentmigrator连接mysql_如何利用FluentMigrator实现数据库迁移
- Kotlin教程(五)类型