这个题目的方法是将圆盘分成一个个圆环,然后判断这些圆环是否被上面的圆覆盖;

如果这个圆的圆周上的圆弧都被上面的覆盖,暂时把它标记为不可见;

然后如果他的头上有个圆,他有个圆弧可见,那么他自己本身可见,并且可以把这条圆弧下面的第一个圆重新标记为可见;

另外,圆弧可见还是不可见利用它的中点来进行判断;

 #include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector> using namespace std; const int maxn = + ;
const double eps = 1e-; //别开太大,样例数据就到达1e-11级别
const double pi = acos(-); int dcmp(double x)
{
return fabs(x) < eps ? : (x > ? : -);
} struct Point
{
double x;
double y; Point(double x = , double y = ):x(x), y(y) {} bool operator < (const Point& e) const
{
return dcmp(x - e.x) < || (dcmp(x - e.x) == && dcmp(y - e.y) < );
} bool operator == (const Point& e) const
{
return dcmp(x - e.x) == && dcmp(y - e.y) == ;
} 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) > ) return ; //这里我选择点在圆边上不算在圆内
else return ;
} 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) <= && dcmp(cdist - rdiff) <= ) return ; //包括重合,内切和内含的情况
return ;
} 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) == )
{
if(dcmp(C1.r - C2.r) == ) return -; //两圆重合
return ; //同心圆但不重合
}
if(dcmp(C1.r + C2.r - d) < ) return ; //外离
if(dcmp(fabs(C1.r - C2.r) - d) > ) return ; //内含
double a = angle(C2.c - C1.c);
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / ( * C1.r * d));
Point p1 = C1.point(a + da);
Point p2 = C1.point(a - da);
if(p1 == p2) return ; //相切
pointAng[c1].push_back(a + da); //相切的点不处理,只要相交的
pointAng[c1].push_back(a - da);
return ;
} void init()
{
for(int i = ; i < n; i++) pointAng[i].clear();
memset(vis, , sizeof(vis));
} void read()
{
for(int i = ; i < n; i++) C[i].read();
} void solve()
{
for(int i = ; i < n; i++) //圆两两相交,得各圆交点集合
for(int j = ; j < n; j++) if(i != j)
GetCircleCircleIntersection(i, j);
for(int i = ; 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 = ; i < n; i++) //判断第i个圆上的弧
{
int sz = pointAng[i].size();
if(!sz) //此圆不与其他圆相交
{
bool ok = ;
for(int k = i+; k < n; k++) if(CircleInCircle(C[i], C[k])) //判上面是否有圆把它覆盖掉
{
ok = ;
break;
}
if(ok) vis[i] = ;
}
else
{
pointAng[i].push_back(pointAng[i][]);
for(int j = ; j < sz; j++) //第i个圆上的第j条弧
{
bool ok = ;
Point pm = C[i].point((pointAng[i][j] + pointAng[i][j+]) / ); //取弧的中点
for(int k = i+; k < n; k++) if(PointInCircle(pm, C[k]))
{
ok = ;
break;
}
if(ok)
{
vis[i] = ;
for(int u = i-; u >= ; u--)if(PointInCircle(pm, C[u])) //把这段圆弧下的圆设为可见
{
vis[u] = ;
break;
}
}
}
}
}
int ret = ;
for(int i = ; i < n; i++) if(vis[i]) ret++;
printf("%d\n", ret);
} int main()
{
while(scanf("%d", &n) == && n)
{
init();
read();
solve();
}
return ;
}

uva 1308 - Viva Confetti的更多相关文章

  1. uva 2572 Viva Confetti

    思路: 小圆面是由小圆弧围成.那么找出每条小圆弧,如果小圆弧,在小圆弧中点上下左右进行微小位移的所得的点一定在一个小圆面内. 找到最后覆盖这个小点的圆一定是可见的. 圆上的点按照相邻依次排序的关键量为 ...

  2. poj1418 Viva Confetti 判断圆是否可见

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Viva Confetti Time Limit: 1000MS   Memory ...

  3. poj 1418 Viva Confetti

    Viva Confetti Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1025   Accepted: 422 Desc ...

  4. ZOJ 1696 Viva Confetti 计算几何

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

  5. UVaLive2572 poj1418 UVa1308 Viva Confetti

    一次放下n个圆 问最终可见的圆的数量 应该是比较经典的问题吧 考虑一个圆与其他每个圆的交点O(n)个 将其割成了O(n)条弧 那么看每条弧的中点 分别向内向外调动eps这个点 则最上面的覆盖这个点的圆 ...

  6. LA2572 Viva Confetti

    题意 PDF 分析 两两圆求交点,对每个圆弧按半径抖动. 时间复杂度\(O(T n^2)\) 代码 #include<iostream> #include<cstdio> #i ...

  7. [GodLove]Wine93 Tarining Round #9

    比赛链接: http://vjudge.net/contest/view.action?cid=48069#overview 题目来源: lrj训练指南---二维几何计算   ID Title Pro ...

  8. POJ 1418 基本操作和圆 离散弧

    Viva Confetti Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 761   Accepted: 319 Descr ...

  9. uva 1354 Mobile Computing ——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5

随机推荐

  1. Dom4j 学习笔记

    dom4j 是一种解析 XML 文档的开放源代码 XML 框架.dom4j下载地址 本文主要记载了一些简单的使用方法. 一.xml文件的解析 dom4j既可以解析普通的xml文件,也可以解析一个Inp ...

  2. iOS之核心动画(Core Animation)

      Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. Core ...

  3. 通过Html5的postMessage和onMessage方法实现跨域跨文档请求访问

    在项目中有应用到不同的子项目,通过不同的二级域名实现相互调用功能.其中一个功能是将播放器作为单独的二级域名的请求接口,其他项目必须根据该二级域名调用播放器.最近需要实现视频播放完毕后的事件触发,调用父 ...

  4. php 中json_decode()和json_encode()的使用方法

    1.json_decode() json_decode (PHP 5 >= 5.2.0, PECL json >= 1.2.0) json_decode — 对 JSON 格式的字符串进行 ...

  5. Unity3D 之UGUI 文本框和编辑框

    这里来讲解一下unity3D自带的UI功能,自带的UI也叫UGUI功能非常的强大,比起NGUI,更加的灵活,让用户能够更加容易的去使用. 首先创建一个文本Text 然后是文本相对应的属性 这里的属性比 ...

  6. Service解析

    Service解析: 运行service有如下两种方式: StartService() 访问者退出,service仍然运行: BindService() 访问者与service绑定,访问者退出,ser ...

  7. Java输出日历

    源码链接:http://pan.baidu.com/s/1o6xeybK

  8. javascript dom 编程艺术笔记 第四章:图片库

    首先先建立一个html文件,建立一个图片库 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q ...

  9. Codevs 3269 混合背包(二进制优化)

    3269 混合背包 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 背包体积为V ,给出N个物品,每个物品占用体积为V ...

  10. 理解Java中的字符串类型

    1.Java内置对字符串的支持: 所谓的内置支持,即不用像C语言通过char指针实现字符串类型,并且Java的字符串编码是符合Unicode编码标准,这也意味着不用像C++那样通过使用string和w ...