UVa 313 - Intervals

contents

  1. 1. Problem
  2. 2. Input
  3. 3. Output
  4. 4. Sample Input
  5. 5. Sample Output
  6. 6. Solution

Problem

In the ceiling in the basement of a newly open developers building a light source has been installed. Unfortunately, the material used to cover the floor is very sensitive to light. It turned out that its expected life time is decreasing dramatically. To avoid this, authorities have decided to protect light sensitive areas from strong light by covering them. The solution was not very easy because, as it is common, in the basement there are different pipelines under the ceiling and the authorities want to install the covers just on those parts of the floor that are not shielded from the light by pipes. To cope with the situation, the first decision was to simplify the real situation and, instead of solving the problem in 3D space, to construct a 2D model first.

Within this model, the x-axis has been aligned with the level of the floor. The light is considered to be a point light source with integer co-ordinates tex2html_wrap_inline36 . The pipes are represented by circles. The center of the circle i has the integer co-ordinates tex2html_wrap_inline40 and an integer radius tex2html_wrap_inline42 . As pipes are made from solid material, circles cannot overlap. Pipes cannot reflect the light and the light cannot go through the pipes. You have to write a program which will determine the non-overlapping intervals on the x-axis where there is, due to the pipes, no light from the light source.

Input

The input file consists of blocks of lines, each of which except the last describes one situation in the basement. The first line of each block contains a positive integer number N < 500 expressing the number of pipes. The second line of the block contains two integers tex2html_wrap_inline48 and tex2html_wrap_inline50 separated by one space. Each of the next N lines of the block contains integers tex2html_wrap_inline54 , tex2html_wrap_inline56 and tex2html_wrap_inline42 , where tex2html_wrap_inline60 . Integers in individual lines are separated by one space. The last block consists of one line containing n = 0.

Output

The output file consists of blocks of lines, corresponding to the blocks in the file (except the last one). One empty line must be put after each block in the output file. Each of the individual lines of the blocks in the output file will contain two real numbers, the endpoints of the interval where there is no light from the given point light source. The reals are exact to two decimal places and separated by one space. The intervals are sorted according to increasing x-coordinate.

Sample Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
6
300 450
70 50 30
120 20 20
270 40 10
250 85 20
220 30 30
380 100 100
1
300 300
300 150 90
1
300 300
390 150 90
0

Sample Output

1
2
3
4
5
6
7
0.72 78.86
88.50 133.94
181.04 549.93
75.00 525.00
300.00 862.50

Solution

題目描述:

現在天花板上面有一盞燈,然後下方有數個圓,請問陰影部分的區間由小至大輸出分別為何。
假設不會有圓的高度大於燈的位置,而陰影呈現在 x 軸上。

題目解法:

求圓 (cx, cy, r) 外一點的切線,由於點 (a, b) 在圓外,通常此點切於圓的線會有兩條。

假設該線斜率為 m,則通過的線為 y = m * (x - a) + b

藉由點線距公式 |m * (cx - a) - cy + b |/sqrt(m*m + 1) = r,求得 m 之後得到兩條切線,往後求交 x 軸的位置即可。(特別考慮 m 不存在的情況)

最後使用掃描線算法來算聯集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
int main() {
int N;
double bx, by, cx, cy, cr;
while (scanf("%d", &N) == 1 && N) {
scanf("%lf %lf", &bx, &by);
vector< pair<double, double> > interval;
for (int i = 0; i < N; i++) {
scanf("%lf %lf %lf", &cx, &cy, &cr);
double a, b, c;
a = (cx - bx) * (cx - bx) - cr * cr;
b = 2 * (cx - bx) * (by - cy);
c = (by - cy) * (by - cy) - cr * cr;
if (b * b - 4 * a * c > 0) {
#define eps 1e-6
if (fabs(a) > eps) {
double m1 = (-b + sqrt(b * b - 4 * a * c))/(2 * a);
double m2 = (-b - sqrt(b * b - 4 * a * c))/(2 * a);
double l, r;
c = by - m1 * bx;
l = -c / m1;
c = by - m2 * bx;
r = -c / m2;
if (l >= r)
swap(l, r);
interval.push_back(make_pair(l, r));
} else {
double m1 = -c / b;
double l, r;
c = by - m1 * bx;
l = -c / m1;
r = bx;
if (l >= r)
swap(l, r);
interval.push_back(make_pair(l, r));
}
}
}
sort(interval.begin(), interval.end());
double coverL, coverR;
coverL = interval[0].first;
coverR = interval[0].second;
for (int i = 0; i < interval.size(); i++) {
if (interval[i].first <= coverR) {
coverR = max(coverR, interval[i].second);
} else {
printf("%.2lf %.2lf\n", coverL, coverR);
coverL = interval[i].first;
coverR = interval[i].second;
}
}
printf("%.2lf %.2lf\n", coverL, coverR);
puts("");
}
return 0;
}