poj1418 Viva Confetti 判断圆是否可见

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud

Viva Confetti

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 881   Accepted: 361

Description

Do you know confetti? They are small discs of colored paper, and people throw them around during parties or festivals. Since people throw lots of confetti, they may end up stacked one on another, so there may be hidden ones underneath.

A handful of various sized confetti have been dropped on a table. Given their positions and sizes, can you tell us how many of them you can see?

The following figure represents the disc configuration for the first sample input, where the bottom disc is still visible.

Input

The input is composed of a number of configurations of the following form.


x1 y1 r1 
x2 y2 r2 
... 
xn yn rn

The first line in a configuration is the number of discs in the configuration (a positive integer not more than 100), followed by one line descriptions of each disc : coordinates of its center and radius, expressed as real numbers in decimal notation, with up to 12 digits after the decimal point. The imprecision margin is +/- 5 x 10^(-13). That is, it is guaranteed that variations of less than +/- 5 x 10^(-13) on input values do not change which discs are visible. Coordinates of all points contained in discs are between -10 and 10.

Confetti are listed in their stacking order, x1 y1 r1 being the bottom one and xn yn rn the top one. You are observing from the top.

The end of the input is marked by a zero on a single line.

Output

For each configuration you should output the number of visible confetti on a single line.

Sample Input

3
0 0 0.5
-0.9 0 1.00000000001
0.9 0 1.00000000001
5
0 1 0.5
1 1 1.00000000001
0 2 1.00000000001
-1 1 1.00000000001
0 -0.00001 1.00000000001
5
0 1 0.5
1 1 1.00000000001
0 2 1.00000000001
-1 1 1.00000000001
0 0 1.00000000001
2
0 0 1.0000001
0 0 1
2
0 0 1
0.00000001 0 1
0

Sample Output

3
5
4
2
2

依照顺序摆放下n个圆,问最终有多少个圆是可见的。

想了好久,然后问了队友shu_mj,想了好一会才想通。

首先,可见部分的一部分的边界一定是圆弧。于是,我们可以先求出所有的圆相交划分的一小段一小段的圆弧,然后把这些小段圆弧的中点稍微往圆内移动一点以及往外移动一点。然后从后放的圆开始判断,最先出现在哪个圆中,那么这个圆就是可见的。

  1 /**
  2  * code generated by JHelper
  3  * More info: https://github.com/AlexeyDmitriev/JHelper
  4  * @author xyiyy @https://github.com/xyiyy
  5  */
  6
  7 #include <iostream>
  8 #include <fstream>
  9
 10 //#####################
 11 //Author:fraud
 12 //Blog: http://www.cnblogs.com/fraud/
 13 //#####################
 14 //#pragma comment(linker, "/STACK:102400000,102400000")
 15 #include <iostream>
 16 #include <sstream>
 17 #include <ios>
 18 #include <iomanip>
 19 #include <functional>
 20 #include <algorithm>
 21 #include <vector>
 22 #include <string>
 23 #include <list>
 24 #include <queue>
 25 #include <deque>
 26 #include <stack>
 27 #include <set>
 28 #include <map>
 29 #include <cstdio>
 30 #include <cstdlib>
 31 #include <cmath>
 32 #include <cstring>
 33 #include <climits>
 34 #include <cctype>
 35
 36 using namespace std;
 37 #define pb(X) push_back(X)
 38 #define rep(X, N) for(int X=0;X<N;X++)
 39 #define ALL(X) (X).begin(),(X).end()
 40
 41 //
 42 // Created by xyiyy on 2015/8/10.
 43 //
 44
 45 #ifndef JHELPER_EXAMPLE_PROJECT_P_HPP
 46 #define JHELPER_EXAMPLE_PROJECT_P_HPP
 47
 48 const double EPS = 4e-13;
 49
 50 double add(double a, double b) {
 51     if (fabs(a + b) < EPS * (fabs(a) + fabs(b)))return 0;
 52     return a + b;
 53 }
 54
 55 class P {
 56 public:
 57     double x, y;
 58
 59     P() { }
 60
 61     P(double x, double y) : x(x), y(y) { }
 62
 63     P  operator+(const P &p) {
 64         return P(add(x, p.x), add(y, p.y));
 65     }
 66
 67     P operator-(const P &p) {
 68         return P(add(x, -p.x), add(y, -p.y));
 69     }
 70
 71     P operator*(const double &d) {
 72         return P(x * d, y * d);
 73     }
 74
 75     P operator/(const double &d) {
 76         return P(x / d, y / d);
 77     }
 78
 79     double dot(P p) {
 80         return add(x * p.x, y * p.y);
 81     }
 82
 83
 84     double abs() {
 85         return sqrt(abs2());
 86     }
 87
 88     double abs2() {
 89         return dot(*this);
 90     }
 91
 92 };
 93
 94
 95
 96 //求两圆的极角 以p为中心
 97 double polarangle(P p, P q) {
 98     return atan2(q.y - p.y, q.x - p.x);
 99 }
100
101
102 #endif //JHELPER_EXAMPLE_PROJECT_P_HPP
103
104 const long double PI2 = 2 * acos(-1.0);
105
106 long double update(double x) {
107     while (x < 0.0)x += PI2;
108     while (x >= PI2)x -= PI2;
109     return x;
110 }
111
112 class poj1418 {
113 public:
114     void solve(std::istream &in, std::ostream &out) {
115         int n;
116         P t;
117         while (in >> n && n) {
118             vector<P> ps;
119             vector<double> rs;
120             vector<bool> cansee(n, 0);
121             rep(i, n) {
122                 double x, y, r;
123                 in >> x >> y >> r;
124                 ps.pb(P(x, y));
125                 rs.pb(r);
126             }
127             rep(i, n) {
128                 vector<double> pp;
129                 pp.pb(0.0);
130                 pp.pb(PI2);
131                 rep(j, n) {
132                     double a = rs[i];
133                     double d = (ps[i] - ps[j]).abs();
134                     double b = rs[j];
135                     if (a + b < d || a + d < b || b + d < a)continue;
136                     double theta = acos((a * a + d * d - b * b) / (2 * a * d));
137                     double alpha = polarangle(ps[i], ps[j]);
138                     pp.pb(update(alpha - theta));
139                     pp.pb(update(alpha + theta));
140                 }
141                 sort(ALL(pp));
142                 rep(j, pp.size() - 1) {
143                     double theta = (pp[j] + pp[j + 1]) / 2;
144                     for (int k = -1; k <= 1; k += 2) {
145                         t.x = ps[i].x + (rs[i] + k * EPS) * cos(theta);
146                         t.y = ps[i].y + (rs[i] + k * EPS) * sin(theta);
147                         int gao = n - 1;
148                         for (; gao >= 0; gao--) {
149                             if ((ps[gao] - t).abs() < rs[gao])break;
150                         }
151                         if (gao != -1)cansee[gao] = 1;
152                     }
153                 }
154             }
155             out << count(ALL(cansee), 1) << endl;
156         }
157     }
158 };
159
160 int main() {
161     std::ios::sync_with_stdio(false);
162     std::cin.tie(0);
163     poj1418 solver;
164     std::istream &in(std::cin);
165     std::ostream &out(std::cout);
166     solver.solve(in, out);
167     return 0;
168 }

代码君

时间: 2024-10-08 01:35:02

poj1418 Viva Confetti 判断圆是否可见的相关文章

uva 1308 - Viva Confetti(几何)

题目链接:uva 1308 - Viva Confetti 枚举一下两圆,处理出所有弧,然后判断每段弧的中点是否可见,可见的话该弧所在的圆也可见,以及该段弧下面的圆也可见. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double pi = 4 * at

ZOJ 1696 Viva Confetti 计算几何

计算几何:按顺序给n个圆覆盖,问最后可以有几个圆被看见... 对每个圆求和其他圆的交点,每两个交点之间就是可能被看到的圆弧,取圆弧的中点,往外扩展一点或者往里缩一点,从上往下判断有没有圆可以盖住这个点,能盖住这个点的最上面的圆一定是可见的 Viva Confetti Time Limit: 2 Seconds      Memory Limit: 65536 KB Do you know confetti? They are small discs of colored paper, and p

POJ1584 A Round Peg in a Ground Hole 凸包判断 圆和凸包的关系

POJ1584 题意:给定n条边首尾相连对应的n个点 判断构成的图形是不是凸多边形 然后给一个圆 判断圆是否完全在凸包内(相切也算) 思路:首先运用叉积判断凸多边形 相邻三条变叉积符号相异则必有凹陷 O(n) 之后首先判断圆心是否在凸多边形内 如果凸多边形的点有序 则可以在logn时间内判断 否则先排序再判断 O(nlogn) 然后用每条边(线段)判断到圆心的距离即可 这道题也没给数据范围 O(nlogn)是可以AC的. #include<iostream> #include<stdio

A Round Peg in a Ground Hole - POJ 1584 (判断凸多边形&amp;判断点在多边形内&amp;判断圆在多边形内)

题目大意:首先给一个圆的半径和圆心,然后给一个多边形的所有点(多边形按照顺时针或者逆时针给的),求,这个多边形是否是凸多边形,如果是凸多边形在判断这个圆是否在这个凸多边形内. 分析:判断凸多边形可以使用相邻的三个点叉积判断,因为不知道顺时针还是逆时针,所以叉积如果有有整数和负数,那么一定不是凸多边形(注意允许多多点在一条线段上).判断圆在凸多边形首先要判断圆心是否在多边形内,如果在多边形内,再次判断圆心到达到变形每条边的最短距离,如果小于半径就是不合法.ps:一道好题,通过这个题学会了不少东西.

poj1584--A Round Peg in a Ground Hole(判断凸包,并且判断圆是否在凸包内)

A Round Peg in a Ground Hole Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5399   Accepted: 1712 Description The DIY Furniture company specializes in assemble-it-yourself furniture kits. Typically, the pieces of wood are attached to on

Viva Confetti(几何+圆盘覆盖问题)

Viva Confetti Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 2572 Appoint description:  System Crawler  (2015-04-19) Description Do you know confetti? They are small discs of colored paper, and p

UVaLive2572 poj1418 UVa1308 Viva Confetti

一次放下n个圆 问最终可见的圆的数量 应该是比较经典的问题吧 考虑一个圆与其他每个圆的交点O(n)个 将其割成了O(n)条弧 那么看每条弧的中点 分别向内向外调动eps这个点 则最上面的覆盖这个点的圆可见O(n) 总时间复杂度O(n ** 3) 怕炸精度,代码基本抄的rjl的 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include&

判断圆和矩形是否相交(非面积相交)

月赛题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1165 题解. 问题很简单,给你一个矩形和一个圆,问你是否他们相交.注意,这里的相交不是面积相交.也就是说,圆在矩形内(且不相切)是不相交的.或者矩形在圆内(且矩形的四个点不在圆上)也是不相交的. 那么,我们怎么来判断呢? 中间轮廓线是矩形的边,各向外和内距离为圆半径r划线(当然,四个角的肯定不太标准). 如果圆心在红色区域的话,肯定是会与圆相交了... 当然,如果我们根本画不出来这

判断圆和矩形是否相交

#include <iostream> #include #include <cstdio> #include <cstring> #include <cmath> using namespace std; const double eps = 1e-8; const double pi = acos(-1); struct POINT {     double x, y;     POINT(double a, double b){         x =