uva 1308 - Viva Confetti
这个题目的方法是将圆盘分成一个个圆环,然后判断这些圆环是否被上面的圆覆盖;
如果这个圆的圆周上的圆弧都被上面的覆盖,暂时把它标记为不可见;
然后如果他的头上有个圆,他有个圆弧可见,那么他自己本身可见,并且可以把这条圆弧下面的第一个圆重新标记为可见;
另外,圆弧可见还是不可见利用它的中点来进行判断;
#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的更多相关文章
- uva 2572 Viva Confetti
思路: 小圆面是由小圆弧围成.那么找出每条小圆弧,如果小圆弧,在小圆弧中点上下左右进行微小位移的所得的点一定在一个小圆面内. 找到最后覆盖这个小点的圆一定是可见的. 圆上的点按照相邻依次排序的关键量为 ...
- poj1418 Viva Confetti 判断圆是否可见
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Viva Confetti Time Limit: 1000MS Memory ...
- poj 1418 Viva Confetti
Viva Confetti Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 1025 Accepted: 422 Desc ...
- ZOJ 1696 Viva Confetti 计算几何
计算几何:按顺序给n个圆覆盖.问最后能够有几个圆被看见.. . 对每一个圆求和其它圆的交点,每两个交点之间就是可能被看到的圆弧,取圆弧的中点,往外扩展一点或者往里缩一点,从上往下推断有没有圆能够盖住这 ...
- UVaLive2572 poj1418 UVa1308 Viva Confetti
一次放下n个圆 问最终可见的圆的数量 应该是比较经典的问题吧 考虑一个圆与其他每个圆的交点O(n)个 将其割成了O(n)条弧 那么看每条弧的中点 分别向内向外调动eps这个点 则最上面的覆盖这个点的圆 ...
- LA2572 Viva Confetti
题意 PDF 分析 两两圆求交点,对每个圆弧按半径抖动. 时间复杂度\(O(T n^2)\) 代码 #include<iostream> #include<cstdio> #i ...
- [GodLove]Wine93 Tarining Round #9
比赛链接: http://vjudge.net/contest/view.action?cid=48069#overview 题目来源: lrj训练指南---二维几何计算 ID Title Pro ...
- POJ 1418 基本操作和圆 离散弧
Viva Confetti Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 761 Accepted: 319 Descr ...
- uva 1354 Mobile Computing ——yhx
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5
随机推荐
- iOS之定位与地图
概览 现在很多社交.电商.团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用 和导航应用所特有的.的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式.例如你到了一 ...
- 一个月的时间--java从一无所有到能用框架做点东西出来
四月20号到六月2号 因为顺利完成了Struts在线考试系统的学习,基本掌握了struts框架的原理和他众多复杂的标签.趁着下一件事情还没到时间,也顾不上写昨天研习的student部分和今天stude ...
- C# 类是怎么执行的?
C# 类是怎么执行的? public class Person{ static person(){} //不写,默认也有个空的 public person(){}//不写,默认也有个空的 public ...
- Struts1和Struts2的区别和对比(完整版)
Struts2其实并不是一个陌生的Web框架,Struts2是以Webwork的设计思想为核心,吸收了Struts1的优点,因此,可以认为Struts2是Struts1和Webwork结合的产物. 简 ...
- WEB开发时Browser控件得到C:\fakepath\ 的解决方式
IE9中JS获得文件上传控件的路径不对,为:C:\fakepath\ 原来要修改: 工具 -> Internet选项 -> 安全 -> 自定义级别 -> 将本地文件上载至服务 ...
- JavaScript高级程序设计(一):JavaScript简介
一.JavaScript实现 1.一个完整的JavaScript包含三个部分组成: 1)ECMAScript 核心 2)DOM文档对象模型 3)BOM浏览器对象模型 2.文档对象模型(DOM) 文档对 ...
- 节点的创建--对比jQuery与JavaScript 方法
一. 创建节点: 节点是DOM结构的基础,根据DOM规范,节点是一个很宽泛的概念,包含元素.属性.文本.文档和注释.但在实际开发中,要动态创建内容,主要操作的节点包括元素.属性和文本. 1.需求:创 ...
- ibatis+spring+cxf+mysql搭建webservice
首先需必备:mysql.myeclipse6.5.apache-cxf-2.6.2 一.建数据库,库名:cxf_demo:表名:book CREATE DATABASE `cxf_demo` --数 ...
- java图片高质量缩放类
import java.awt.Color;import java.awt.Graphics;import java.awt.Image;import java.awt.image.BufferedI ...
- apache常用工作模式的区别
apache常用工作模式有两种 worker模式1.线程模式2.占用资源少3.稳定性略差4.并发大 prefork模式1.进程模式2.占用资源多3.稳定4.并发一般 来自为知笔记(Wiz)