思路:

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

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

圆上的点按照相邻依次排序的关键量为极角(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. hibernate hql 大全

    Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL.但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态 和关联之类的概念. ...

  2. mac忘记密码的解决办法

    开机, 启动时按"cmd+S".这时,你会进入Single User Model,出现像DOS一样的提示符 #root>.请在#root>下 输入 (注意空格, 大小写 ...

  3. c++内存中字节对齐问题详解

    一.什么是字节对齐,为什么要对齐?    现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址 ...

  4. ZOJ 3778 Talented Chef

    题目链接 题意 : 这个人需要做n道菜,每道菜Ai步,他可以同时做M道不同的菜的其中一步,问你最少需要多少时间能做完所有的菜. 思路 : 这个题比赛的时候禁锢思路了,根本没想出来,就是当M > ...

  5. mysql 查询重复值命令

    积累备忘啊: ; 从t_maintenanceinfo表查询重复记录的mtiId 和ip字段,以及重复条数

  6. sql快捷键

    请柬:https://msdn.microsoft.com/zh-cn/library/ms174205.aspx

  7. C++不同进制整数

    在C++的整数常量中,整数分为十进制整数.八进制整数和十六进制整数. 那给出一个整型常量怎样区分是何种进制呢?/给出一个整型常量,如100,默认是十进制数,如果在该数前加0,如0100,则此数表示为八 ...

  8. 删除appcompat_v7会出很多错误

    创建工程的时候会出现appcompat_v7这个文件夹 手贱删除后,发现出错了 说明test项目是依赖于appcompat_v7包的,所以这个appcompat_v7包是不能被删除的. appcomp ...

  9. profile工具

    gprof callgrind vtune(待使用) ----time命令(待学习) ps -u <username> -H -opid,cmd strace

  10. Flash Builder 4.6 找不到所需的Adobe Flash Player

    问题: 安装完Flash Builder 4.6 ,第一次运行项目,出现如下错误提示: “Flash Builder 找不到所需版本的 Adobe Flash Player.您可能需要安装该版本的 F ...