思路:

小圆面是由小圆弧围成。那么找出每条小圆弧,如果小圆弧,在小圆弧中点上下左右进行微小位移的所得的点一定在一个小圆面内。

找到最后覆盖这个小点的圆一定是可见的。

圆上的点按照相邻依次排序的关键量为极角(0,2PI)

用中心点代替圆弧本身是否被圆覆盖

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<memory.h>
#include<cstdlib>
#include<vector>
#define clc(a,b) memset(a,b,sizeof(a))
#define LL long long int
#define up(i,x,y) for(i=x;i<=y;i++)
#define w(a) while(a)
using namespace std;
const int inf=0x3f3f3f3f;
const int N = ;
const double eps = *1e-;
const double pi = acos(-); int dcmp(double x)
{
if(fabs(x) < eps) return ;
else return x < ? - : ;
} const double PI = acos(-);
const double TWO_PI = PI * ; double NormalizeAngle(double rad, double center = PI)
{
return rad - TWO_PI * floor((rad + PI - center) / TWO_PI);
} struct Point
{
double x, y;
Point(double x=, double y=):x(x),y(y) { }
}; typedef Point Vector; Vector operator + (Vector A, Vector 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 * (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);
} 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);
} // 交点相对于圆1的极角保存在rad中
void getCircleCircleIntersection(Point c1, double r1, Point c2, double r2, vector<double>& rad)
{
double d = Length(c1 - c2);
if(dcmp(d) == ) return; // 不管是内含还是重合,都不相交
if(dcmp(r1 + r2 - d) < ) return;
if(dcmp(fabs(r1-r2) - d) > ) return; double a = angle(c2 - c1);
double da = acos((r1*r1 + d*d - r2*r2) / (*r1*d));
rad.push_back(NormalizeAngle(a-da));
rad.push_back(NormalizeAngle(a+da));
} const int maxn = + ;
int n;
Point center[maxn];
double radius[maxn];
bool vis[maxn]; // 覆盖点p的最上层的圆
int topmost(Point p)
{
for(int i = n-; i >= ; i--)
if(Length(center[i]-p) < radius[i]) return i;
return -;
} int main()
{
while(cin >> n)
{
if(!n) break;
for(int i = ; i < n; i++)
{
double x, y, r;
cin >> x >> y >> r;
center[i] = Point(x, y);
radius[i] = r;
}
memset(vis, , sizeof(vis));
for(int i = ; i < n; i++)
{
// 考虑圆i被切割成的各个圆弧。把圆周当做区间来处理,起点是0,终点是2PI
vector<double> rad;
rad.push_back();
rad.push_back(PI*);
for(int j = ; j < n; j++)
getCircleCircleIntersection(center[i], radius[i], center[j], radius[j], rad);
sort(rad.begin(), rad.end()); for(int j = ; j < rad.size(); j++)
{
double mid = (rad[j] + rad[j+]) / 2.0; // 圆弧中点相对于圆i圆心的极角
for(int side = -; side <= ; side += )
{
double r2 = radius[i] - side*eps; // 往里面或者外面稍微一动一点点
int t = topmost(Point(center[i].x + cos(mid)*r2, center[i].y + sin(mid)*r2));
if(t >= ) vis[t] = true;
}
}
}
int ans = ;
for(int i = ; i < n; i++) if(vis[i]) ans++;
cout << ans << "\n";
}
return ;
}

uva 2572 Viva Confetti的更多相关文章

  1. uva 1308 - 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 10969 (圆与圆之间的覆盖问题) Sweet Dream

    题意: 有n个按先后顺序放置的不同大小不同位置的圆,求所有可见圆弧的长度. 分析: 这道题应该是大白书上例题 LA 2572 (求可见圆盘的数量) Kanazawa 的加强版,整体框架都差不多. 对于 ...

随机推荐

  1. Mybatis+SpringMVC的项目环境搭建

    一.web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=&qu ...

  2. codeforces #313 div1 A

    捕获一只野生大水题! 首先我们知道边长为L的正三角形含有边长为1的小正三角形为L^2个 那么我们可以通过在六边形的正上,左下,右下补充正三角形使得原图形变成正三角形 然后再将补充的减去即可 #incl ...

  3. [itint5]两有序数组的交和并

    这一题也简单,唯一有意思的地方是提炼了一个函数用来做数组索引去重前进. int forward(vector<int> &arr, int i) { while (i+1 < ...

  4. iOS开发--TableView详细解释

    -.建立 UITableView  DataTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 420)];  [Data ...

  5. MYSQL 优化建议

    转自 http://coolshell.cn/articles/1846.html MYSQL 优化建议20条 1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效 ...

  6. 93. Restore IP Addresses

    题目: Given a string containing only digits, restore it by returning all possible valid IP address com ...

  7. 绕过图片格式限制上传木马获取WebShell

    思路: 图片上传功能中,前端页面上传的是.png格式的图片文件,但是抓包Request中修改图片后缀为.php 可以绕过对上传文件格式的限制,文件的上传路径可以在上传后的页面或查看上传成功后的resp ...

  8. Yii CActiveForm

    http://blog.sina.com.cn/s/blog_685213e70101mo4i.html 文档: http://www.yiiframework.com/doc/api/1.1/CAc ...

  9. 【原创】ZYNQ学习笔记(一) HelloWorld实现

    拿过ZYNQ开发板,里面给了很多部件,果断从网上下载了手册,N多手册和原理图. 要比Spartan-6复杂多了,耐心地看了看,知道ZYNQ系列分为PS(系统)以及PL(逻辑)部分. 之前,自己一直在做 ...

  10. C#中保留2位小数

    public static void Method() { double a = 1.991; a = Math.Round(a); Console.WriteLine("a = {0}&q ...