LA - 2572 - Viva Confetti
来源:互联网 发布:幻想神域软件 编辑:程序博客网 时间:2024/05/01 08:29
题意:先后给出n个圆,问最后能看到多少个圆(n <= 100,输入数据小数位数可达12位)。
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=573
——>>圆两两相交,得到交点(保存其极角就行),每个圆内交点的极角排序,扫描每一小段弧,判断其弧中点(不是弦中点)是否在上面的圆内,若这段小弧可见,再将其能看到的下面的第一个圆设为可见。
注意:精度eps不能太大。
#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int maxn = 100 + 10;const double eps = 1e-14; //别开太大,样例数据就到达1e-11级别const double pi = acos(-1);int dcmp(double x){ return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);}struct Point{ double x; double y; Point(double x = 0, double y = 0):x(x), y(y){} bool operator < (const Point& e) const{ return dcmp(x - e.x) < 0 || (dcmp(x - e.x) == 0 && dcmp(y - e.y) < 0); } bool operator == (const Point& e) const{ return dcmp(x - e.x) == 0 && dcmp(y - e.y) == 0; } int read(){ return scanf("%lf%lf", &x, &y); }};typedef Point Vector;Vector operator + (Point A, Point B){ return Vector(A.x + B.x, A.y + B.y);}Vector operator - (Point A, Point B){ return Vector(A.x - B.x, A.y - B.y);}Vector operator * (Point A, double p){ return Vector(A.x * p, A.y * p);}Vector operator / (Point A, double p){ return Vector(A.x / p, A.y / p);}struct Circle{ Point c; double r; Circle(){} Circle(Point c, double r):c(c), r(r){} int read(){ return scanf("%lf%lf%lf", &c.x, &c.y, &r); } Point point(double a){ return Point(c.x + r * cos(a), c.y + r * sin(a)); }};double Dot(Vector A, Vector B){ return A.x * B.x + A.y * B.y;}double Length(Vector A){ return sqrt(Dot(A, A));}double angle(Vector v){ //求向量的极角 return atan2(v.y, v.x);}bool PointInCircle(Point p, Circle C){ //判断点是否在圆内 double dist = Length(p - C.c); if(dcmp(dist - C.r) > 0) return 0; //这里我选择点在圆边上不算在圆内 else return 1;}bool CircleInCircle(Circle A, Circle B){ //判断圆在圆内 double cdist = Length(A.c - B.c); double rdiff = B.r - A.r; if(dcmp(A.r - B.r) <= 0 && dcmp(cdist - rdiff) <= 0) return 1; //包括重合,内切和内含的情况 return 0;}int n;Circle C[maxn];bool vis[maxn];vector<double> pointAng[maxn];int GetCircleCircleIntersection(int c1, int c2){ //求圆与圆的交点 Circle C1 = C[c1]; Circle C2 = C[c2]; double d = Length(C1.c - C2.c); if(dcmp(d) == 0){ if(dcmp(C1.r - C2.r) == 0) return -1; //两圆重合 return 0; //同心圆但不重合 } if(dcmp(C1.r + C2.r - d) < 0) return 0; //外离 if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0; //内含 double a = angle(C2.c - C1.c); double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d)); Point p1 = C1.point(a + da); Point p2 = C1.point(a - da); if(p1 == p2) return 1; //相切 pointAng[c1].push_back(a + da); //相切的点不处理,只要相交的 pointAng[c1].push_back(a - da); return 2;}void init(){ for(int i = 0; i < n; i++) pointAng[i].clear(); memset(vis, 0, sizeof(vis));}void read(){ for(int i = 0; i < n; i++) C[i].read();}void solve(){ for(int i = 0; i < n; i++) //圆两两相交,得各圆交点集合 for(int j = 0; j < n; j++) if(i != j) GetCircleCircleIntersection(i, j); for(int i = 0; i < n; i++){ sort(pointAng[i].begin(), pointAng[i].end()); //各圆交点按极角排序 vector<double>::iterator iter = unique(pointAng[i].begin(), pointAng[i].end()); //去重,可减少运行时间,不去重也能AC pointAng[i].resize(distance(pointAng[i].begin(), iter)); } for(int i = 0; i < n; i++){ //判断第i个圆上的弧 int sz = pointAng[i].size(); if(!sz){ //此圆不与其他圆相交 bool ok = 1; for(int k = i+1; k < n; k++) if(CircleInCircle(C[i], C[k])){ //判上面是否有圆把它覆盖掉 ok = 0; break; } if(ok) vis[i] = 1; } else{ pointAng[i].push_back(pointAng[i][0]); for(int j = 0; j < sz; j++){ //第i个圆上的第j条弧 bool ok = 1; Point pm = C[i].point((pointAng[i][j] + pointAng[i][j+1]) / 2); //取弧的中点 for(int k = i+1; k < n; k++) if(PointInCircle(pm, C[k])){ ok = 0; break; } if(ok){ vis[i] = 1; for(int u = i-1; u >= 0; u--)if(PointInCircle(pm, C[u])){ //把这段圆弧下的圆设为可见 vis[u] = 1; break; } } } } } int ret = 0; for(int i = 0; i < n; i++) if(vis[i]) ret++; printf("%d\n", ret);}int main(){ //freopen("data.txt", "r", stdin); //提交时忘了注释掉这个吃了2个WA。。。 while(scanf("%d", &n) == 1 && n){ init(); read(); solve(); } return 0;}
- LA - 2572 - Viva Confetti
- LA 2572 - Viva Confetti
- LA 2572 Viva Confetti 离散化 *
- LA 2572 Viva Confetti Kanazawa - 2002/2003 平面上的圆盘
- zoj 1696 Viva Confetti
- zoj 1696 Viva Confetti
- zoj 1696 Viva Confetti
- POJ 1418 Viva Confetti
- POJ 1418 Viva Confetti
- uva1308 Viva Confetti
- LA2572 Viva Confetti 计算几何
- poj 1418 || zoj 1696 Viva Confetti
- POJ 1418 Viva Confetti(Japan 2002 Kanazawa)
- ZOJ 1696 Viva Confetti 计算几何
- Viva Confetti(几何+圆盘覆盖问题)
- uva 1308 - Viva Confetti(几何)
- POJ 1418 Viva Confetti 已翻译
- 《viva la vida》 歌词
- 黑马程序员——集合框架(二)
- C++类静态成员的初始化
- Android中WIFI 架构和控制流程
- 在C#中类似C++标准库中关联容器map介绍
- 反射(Reflection)枚举创建DataTable
- LA - 2572 - Viva Confetti
- uva 11111 Generalized Matrioshkas
- 访问sdcard
- android 深入理解AnsyncTask
- POJ1050简单动态规划:区间DP
- 浅谈大数据背景下的计算机体系结构存储层次结构研究
- 统计学习方法概论
- UVA11800 Determine the Shape
- [leetcode]Triangle