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

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

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

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

 #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. Kafka 0.8: 多日志文件夹机制

    kafka 0.7.2 中对log.dir的定义如下: log.dir none Specifies the root directory in which all log data is kept. ...

  2. JSON 与List转换类封装

    json与list转换小结: import java.util.ArrayList; import java.util.List; import com.google.gson.Gson; impor ...

  3. 使用ASP.NET实现Windows Service定时执行任务

    转载http://blog.csdn.net/yanghua_kobe/article/details/6937816 我们怎样才能在服务器上使用asp.net定时执行任务而不需要安装windows ...

  4. git研究1

    error:src refspec master does not match any  将本地GIT版本库PUSH到一个GITHUB上一个空的版本库时出现错误,本地版本库为空, 空目录不能提交 (只 ...

  5. iOS开发——百度地图SDK集成

    (正在形成文档,待更新……)

  6. TFTPD32, 3CDaemon, FlashFxp

    TFTPD32, 3CDaemon, FlashFxp ——各种网络传输下载工具简介—— 一.将3CDaemon.exe作为TFTP服务端,开发板作为TFTP客户端 1.如上图所示,设置好3CDaem ...

  7. Codevs 1198 国王游戏 2012年NOIP全国联赛提高组

    1198 国王游戏 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 恰逢 H 国国庆,国王邀 ...

  8. 不对称密钥密码体系之RSA

    公钥密码的特性: 1.加密和解密使用不同的钥匙 2.从一个钥匙推出另一个钥匙在计算上不可行 3.每个钥匙都可以做加密和解密 RSA算法: 1978年, MIT三位数学家 R.L.Rivest,A.Sh ...

  9. Java Servlet 接收上传文件

    在Java中使用 Servlet 来接收用户上传的文件,需要用到两个apache包,分别是 commons-fileupload 和 commons-io 包: 如果直接在doPost中,使用requ ...

  10. 用PHP Session和Javascript实现文件上传进度条,处理进度条

    参考http://www.pureweber.com/article/php-upload-progress/ php显示处理进度条http://blog.csdn.net/boabc2304/art ...