poj 1375 Intervals
2014-12-29 08:21
387 查看
Description
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 [bx,by]. The pipes are represented by circles.
The center of the circle i has the integer co-ordinates [cxi,cyi]
and an integer radius ri. 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 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
bx and by separated by one space. Each of the next N lines of the
block contains integers cxi, cyi and ri, where cyi + ri
< by. Integers in individual lines are separated by
one space. The last block consists of one line containing n =
0.
Output
The output consists
of blocks of lines, corresponding to the blocks in the input(except
the last one). One empty line must be put after each block in the
output. Each of the individual lines of the blocks in the output
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
Sample Output
Source
Central Europe 1996
题目大意:在(bx,by)的位置上有一个光源。y=0是地面。在光源和地面之间有N个水管,圆心坐标分别为(cxi,cyi),半径为ri,且满足cyi+ri<by。求地面上不能被光照到的区间。
//==========================================================================================
这题N很小,只要求出光线被每个水管遮挡住的区间,再合并下输出即可。
但这里涉及到一个问题:怎么在知道了一个圆的圆心坐标及半径和圆外一点坐标的情况下求解过这个定点关于圆的两条切线方程?
如图:
已知A点坐标,O点坐标,可以求向量AO。又知道圆心O点的坐标,根据勾股定理可以求出AC的长度。这样,求切线AO,AD就可以转化为已知旋转角为∠CAO的大小,求AO向量经过顺时针和逆时针旋转后的向量。这里已经知道了旋转角sin和cos的值(即CO/AO,AC/AO),结果就更加精确了。
具体的向量旋转方法请参见:http://blog.sina.com.cn/s/blog_7c4c33190100u7mm.html
AC
CODE
program
pku_1375;
type line=record
x,y:real;
end;
var x,y,r,x1,y1,x2,y2:array[0..500] of real;
ox,oy:real;
n:longint;
//============================================================================
function clockwise(x,y,si,co:real):line;
begin
clockwise.x:=y*si+x*co;
clockwise.y:=y*co-x*si;
end;
//============================================================================
function anti_clockwise(x,y,si,co:real):line;
begin
anti_clockwise.x:=-y*si+x*co;
anti_clockwise.y:=y*co+x*si;
end;
//============================================================================
procedure qsort(l,r:longint);
var k,t:real;
i,j:longint;
begin
k:=x1[(l+r) shr 1]; i:=l; j:=r;
repeat
while
x1[i]<k do inc(i);
while
x1[j]>k do dec(j);
if
i<=j then
begin
t:=x1[i]; x1[i]:=x1[j]; x1[j]:=t;
t:=y1[i]; y1[i]:=y1[j]; y1[j]:=t;
inc(i); dec(j);
end;
until i>j;
if j>l then qsort(l,j);
if r>i then qsort(i,r);
end;
//============================================================================
procedure work;
var i,tot:longint;
l1,l2:line;
a,b,c:real;
begin
readln(n); if n=0 then halt;
readln(ox,oy);
for i:=1 to n do
begin
readln(x[i],y[i],r[i]); a:=r[i];
c:=sqrt(sqr(x[i]-ox)+sqr(y[i]-oy));
b:=sqrt(sqr(c)-sqr(a));
l1:=clockwise(x[i]-ox,y[i]-oy,a/c,b/c);
l2:=anti_clockwise(x[i]-ox,y[i]-oy,a/c,b/c);
x1[i]:=ox-oy*l1.x/l1.y; y1[i]:=ox-oy*l2.x/l2.y;
end;
qsort(1,n); tot:=0; y2[0]:=-maxlongint;
for i:=1 to n do
begin
if
x1[i]>y2[tot] then
begin
inc(tot);
x2[tot]:=x1[i]; y2[tot]:=y1[i];
end
else
if
y1[i]>y2[tot] then y2[tot]:=y1[i];
end;
for i:=1 to tot do writeln(x2[i]:0:2,'
',y2[i]:0:2);
writeln;
end;
//============================================================================
begin
while true do work;
end.
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 [bx,by]. The pipes are represented by circles.
The center of the circle i has the integer co-ordinates [cxi,cyi]
and an integer radius ri. 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 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
bx and by separated by one space. Each of the next N lines of the
block contains integers cxi, cyi and ri, where cyi + ri
< by. Integers in individual lines are separated by
one space. The last block consists of one line containing n =
0.
Output
The output consists
of blocks of lines, corresponding to the blocks in the input(except
the last one). One empty line must be put after each block in the
output. Each of the individual lines of the blocks in the output
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
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
0.72 78.86 88.50 133.94 181.04 549.93 75.00 525.00 300.00 862.50
Source
Central Europe 1996
题目大意:在(bx,by)的位置上有一个光源。y=0是地面。在光源和地面之间有N个水管,圆心坐标分别为(cxi,cyi),半径为ri,且满足cyi+ri<by。求地面上不能被光照到的区间。
//==========================================================================================
这题N很小,只要求出光线被每个水管遮挡住的区间,再合并下输出即可。
但这里涉及到一个问题:怎么在知道了一个圆的圆心坐标及半径和圆外一点坐标的情况下求解过这个定点关于圆的两条切线方程?
如图:
已知A点坐标,O点坐标,可以求向量AO。又知道圆心O点的坐标,根据勾股定理可以求出AC的长度。这样,求切线AO,AD就可以转化为已知旋转角为∠CAO的大小,求AO向量经过顺时针和逆时针旋转后的向量。这里已经知道了旋转角sin和cos的值(即CO/AO,AC/AO),结果就更加精确了。
具体的向量旋转方法请参见:http://blog.sina.com.cn/s/blog_7c4c33190100u7mm.html
AC
CODE
program
pku_1375;
type line=record
x,y:real;
end;
var x,y,r,x1,y1,x2,y2:array[0..500] of real;
ox,oy:real;
n:longint;
//============================================================================
function clockwise(x,y,si,co:real):line;
begin
clockwise.x:=y*si+x*co;
clockwise.y:=y*co-x*si;
end;
//============================================================================
function anti_clockwise(x,y,si,co:real):line;
begin
anti_clockwise.x:=-y*si+x*co;
anti_clockwise.y:=y*co+x*si;
end;
//============================================================================
procedure qsort(l,r:longint);
var k,t:real;
i,j:longint;
begin
k:=x1[(l+r) shr 1]; i:=l; j:=r;
repeat
while
x1[i]<k do inc(i);
while
x1[j]>k do dec(j);
if
i<=j then
begin
t:=x1[i]; x1[i]:=x1[j]; x1[j]:=t;
t:=y1[i]; y1[i]:=y1[j]; y1[j]:=t;
inc(i); dec(j);
end;
until i>j;
if j>l then qsort(l,j);
if r>i then qsort(i,r);
end;
//============================================================================
procedure work;
var i,tot:longint;
l1,l2:line;
a,b,c:real;
begin
readln(n); if n=0 then halt;
readln(ox,oy);
for i:=1 to n do
begin
readln(x[i],y[i],r[i]); a:=r[i];
c:=sqrt(sqr(x[i]-ox)+sqr(y[i]-oy));
b:=sqrt(sqr(c)-sqr(a));
l1:=clockwise(x[i]-ox,y[i]-oy,a/c,b/c);
l2:=anti_clockwise(x[i]-ox,y[i]-oy,a/c,b/c);
x1[i]:=ox-oy*l1.x/l1.y; y1[i]:=ox-oy*l2.x/l2.y;
end;
qsort(1,n); tot:=0; y2[0]:=-maxlongint;
for i:=1 to n do
begin
if
x1[i]>y2[tot] then
begin
inc(tot);
x2[tot]:=x1[i]; y2[tot]:=y1[i];
end
else
if
y1[i]>y2[tot] then y2[tot]:=y1[i];
end;
for i:=1 to tot do writeln(x2[i]:0:2,'
',y2[i]:0:2);
writeln;
end;
//============================================================================
begin
while true do work;
end.
相关文章推荐
- poj&nbsp;1201&nbsp;Intervals&nbsp;(差分约束)
- poj&nbsp;3225&nbsp;Help&nbsp;with&nbsp;Intervals
- poj&nbsp;1716&nbsp;Integer&nbsp;Intervals(差分…
- POJ 1018 Communication System
- POJ 2039 To and Fro
- POJ 2247 Humble Numbers
- POJ 1753 Flip Game
- Poj 2886 Who Gets the Most Candi…
- ZZULI_SummerPractice(3) POJ 3598…
- POJ 3185 The Water Bowls
- POj 2379 ACM Rank Table
- POJ 1256 Anagram(全排列问题)
- poj 1201 Intervals & 1716 Integer Intervals 差分约束
- POJ 1664 放苹果
- ZZULI_SummerPractice(3) POJ 12…
- POJ 2182 Lost Cows
- poj 1375 Intervals(计算圆的切线)
- POJ 1375 Intervals(解析几何)
- POJ 1182 食物链
- POJ 2236 Wireless Network